diff options
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_ddr.c')
-rw-r--r-- | FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_ddr.c | 4692 |
1 files changed, 4692 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_ddr.c b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_ddr.c new file mode 100644 index 000000000..6dce74328 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_ddr.c @@ -0,0 +1,4692 @@ +/******************************************************************************* + * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions. + * + * SPDX-License-Identifier: MIT + * + * MPFS HAL Embedded Software + * + */ + +/******************************************************************************* + * @file mss_ddr.h + * @author Microchip-FPGA Embedded Systems Solutions + * @brief DDR related code + * + */ +#include <string.h> +#include <stdio.h> +#include "mpfs_hal/mss_hal.h" +#ifdef DDR_SUPPORT +#include "mss_ddr_debug.h" +#include "simulation.h" +#ifdef FABRIC_NOISE_TEST +#include "drivers/mss_gpio/mss_gpio.h" +#endif + +/******************************************************************************* + * Local Defines + */ +/* This string is updated if any change to ddr driver */ +#define DDR_DRIVER_VERSION_STRING "0.2.003" +/* Version | Comment */ +/* 0.2.003 | Updated SEG setup to match Libero 12.7, Removed warnings, */ +/* | shortened timeout in mtc_test */ +/* 0.2.002 | MTC_test() update -added more tests */ +/* 0.2.001 | Reverted ADDCMD training command */ +/* 0.2.000 | RPC166 now does short retrain by default */ +/* 0.1.009 | Removed AXI overrides. Agreed better placed in */ +/* | mss_sw_config.h util until corrected in configurator v3.0 */ +/* 0.1.008 | Added manual addcmd traing for all variants */ +/* 0.1.007 | Added some updates from SVG and DCT. Also overrides AXI */ +/* | ranges if incorrectly set (Liber0 v12.5 and Liber0 v12.6 */ +/* 0.1.006 | Added tuning for rpc166, read lane FIFO alignement */ +/* 0.1.005 | Added parameter to modify rpc166, lane out of sync on read */ +/* 0.1.004 | Corrected default RPC220 setting so dq/dqs window centred */ +/* 0.1.003 | refclk_phase correctly masked during bclk sclk sw training */ +/* 0.1.002 | Reset modified- corrects softreset on retry issue (1.8.x) */ +/* 0.1.001 | Reset modified- corrects softreset on retry issue (1.7.2) */ +/* 0.0.016 | Added #define DDR_FULL_32BIT_NC_CHECK_EN to mss_ddr.h */ +/* 0.0.016 | updated mss_ddr_debug.c with additio of 32-bit write test */ +/* 0.0.015 | DDR3L - Use Software Bclk Sclk training */ +/* 0.0.014 | DDR3 and DDR update to sync with SVG proven golden version */ +/* 0.0.013 | Added code to turn off DM if DDR4 and using ECC */ +/* 0.0.012 | Added support for turning off unused I/O from Libero */ + +/* + * Calibration data records calculated write calibration values during training + */ +mss_ddr_calibration calib_data; + +/* rx lane FIFO used for tuning */ +#if (TUNE_RPC_166_VALUE == 1) +static uint32_t rpc_166_fifo_offset; +#endif + +/* + * This string is used as a quick sanity check of write/read to DDR. + * The memory test core is used for more comprehensive testing during and + * post calibration + */ +#ifdef DDR_SANITY_CHECKS_EN +static const uint32_t test_string[] = { + 0x12345678,23211234,0x35675678,0x4456789,0x56789123,0x65432198,\ + 0x45673214,0xABCD1234,0x99999999,0xaaaaaaaa,0xbbbbbbbb,0xcccccccc,\ + 0xdddddddd,0xeeeeeeee,0x12121212,0x12345678}; +#endif + +/******************************************************************************* + * external functions + */ +#ifdef DEBUG_DDR_INIT +extern mss_uart_instance_t *g_debug_uart; +extern uint32_t tip_register_status (mss_uart_instance_t *g_mss_uart_debug_pt); +#endif + +/* Use to record instance of errors during calibration */ +static uint32_t ddr_error_count; +#ifdef SWEEP_ENABLED +uint8_t sweep_results[MAX_NUMBER_DPC_VS_GEN_SWEEPS]\ + [MAX_NUMBER_DPC_H_GEN_SWEEPS]\ + [MAX_NUMBER_DPC_V_GEN_SWEEPS]\ + [MAX_NUMBER__BCLK_SCLK_OFFSET_SWEEPS]\ + [MAX_NUMBER_ADDR_CMD_OFFSET_SWEEPS]; +#define TOTAL_SWEEPS (MAX_NUMBER_DPC_H_GEN_SWEEPS*MAX_NUMBER_DPC_H_GEN_SWEEPS*\ + MAX_NUMBER_DPC_V_GEN_SWEEPS*MAX_NUMBER__BCLK_SCLK_OFFSET_SWEEPS*\ + MAX_NUMBER_ADDR_CMD_OFFSET_SWEEPS) +#endif + +/******************************************************************************* + * Local function declarations + */ +static uint32_t ddr_setup(void); +static void init_ddrc(void); +static uint8_t write_calibration_using_mtc(uint8_t num_of_lanes_to_calibrate); +/*static uint8_t mode_register_write(uint32_t MR_ADDR, uint32_t MR_DATA);*/ +static uint8_t MTC_test(uint8_t mask, uint64_t start_address, uint32_t size, MTC_PATTERN pattern, MTC_ADD_PATTERN add_pattern, uint32_t *error); +#ifdef VREFDQ_CALIB +static uint8_t FPGA_VREFDQ_calibration_using_mtc(void); +static uint8_t VREFDQ_calibration_using_mtc(void); +#endif +#ifdef DDR_SANITY_CHECKS_EN +static uint8_t rw_sanity_chk(uint64_t * address, uint32_t count); +static uint8_t mtc_sanity_check(uint64_t start_address); +#endif +#ifdef SET_VREF_LPDDR4_MODE_REGS +static uint8_t mode_register_write(uint32_t MR_ADDR, uint32_t MR_DATA); +#endif +#ifdef DDR_SANITY_CHECKS_EN +static uint8_t memory_tests(void); +#endif +static void ddr_off_mode(void); +static void set_ddr_mode_reg_and_vs_bits(uint32_t dpc_bits); +static void set_ddr_rpc_regs(DDR_TYPE ddr_type); +static uint8_t get_num_lanes(void); +static void load_dq(uint8_t lane); +static uint8_t use_software_bclk_sclk_training(DDR_TYPE ddr_type); +static void config_ddr_io_pull_up_downs_rpc_bits(DDR_TYPE ddr_type); +#ifdef SWEEP_ENABLED +static uint8_t get_best_sweep(sweep_index *good_index); +#endif +#ifdef MANUAL_ADDCMD_TRAINIG +static uint8_t ddr_manual_addcmd_refclk_offset(DDR_TYPE ddr_type, uint8_t * refclk_sweep_index); +#endif + +/******************************************************************************* + * External function declarations + */ +extern void delay(uint32_t n); + +#ifdef DEBUG_DDR_INIT +extern mss_uart_instance_t *g_debug_uart; +#ifdef DEBUG_DDR_DDRCFG +void debug_read_ddrcfg(void); +#endif +#endif + +#ifdef FABRIC_NOISE_TEST +uint32_t fabric_noise_en = 1; +uint32_t fabric_noise_en_log = 1; +uint32_t num_of_noise_blocks_en = 3; /* do not set less than 1 */ +uint32_t noise_ena = 0x0; +#endif + +/******************************************************************************* + * Instance definitions + */ + +/******************************************************************************* + * Public Functions - API + ******************************************************************************/ + + +/***************************************************************************//** + * ddr_state_machine(DDR_SS_COMMAND) + * call this routine if you do not require the state machine + * + * @param ddr_type + */ +uint32_t ddr_state_machine(DDR_SS_COMMAND command) +{ + static DDR_SM_STATES ddr_state; + static uint32_t return_status; + if (command == DDR_SS__INIT) + { + ddr_state = DDR_STATE_INIT; + } + SIM_FEEDBACK0(100U + ddr_state); + SIM_FEEDBACK1(ddr_state); + switch (ddr_state) + { + default: + case DDR_STATE_INIT: + ddr_state = DDR_STATE_TRAINING; + return_status = 0U; + break; + + case DDR_STATE_TRAINING: + /* + * We stay in this state until finished training/fail training + */ + return_status = ddr_setup(); + break; + + case DDR_STATE_MONITOR: + /* + * 1. Periodically check DDR access + * 2. Run any tests, as directed + */ +// return_status = ddr_monitor(); + break; + } + SIM_FEEDBACK1(0xFF000000UL + return_status); + return (return_status); +} + + +/***************************************************************************//** + * ddr_setup(DDR_TYPE ddr_type) + * call this routine if you do not require the state machine + * + * @param ddr_type + */ +static uint32_t ddr_setup(void) +{ + static DDR_TRAINING_SM ddr_training_state = DDR_TRAINING_INIT; + static uint32_t error; + static uint32_t timeout; +#ifdef DEBUG_DDR_INIT + static uint32_t addr_cmd_value; + static uint32_t bclk_sclk_offset_value; + static uint32_t dpc_vrgen_v_value; + static uint32_t dpc_vrgen_h_value; + static uint32_t dpc_vrgen_vs_value; +#endif +#ifdef SWEEP_ENABLED + static SWEEP_STATES sweep_state = INIT_SWEEP; +#endif + static uint32_t retry_count; + static uint32_t write_latency; + static uint32_t tip_cfg_params; + static uint32_t dpc_bits; + static uint8_t last_sweep_status; +#if (TUNE_RPC_166_VALUE == 1) + static uint8_t num_rpc_166_retires = 0U; +#endif +#ifdef MANUAL_ADDCMD_TRAINIG + static uint8_t refclk_offset; + static uint8_t refclk_sweep_index =0xFU; +#endif + static uint32_t bclk_answer = 0U; + DDR_TYPE ddr_type; + uint32_t ret_status = 0U; + uint8_t number_of_lanes_to_calibrate; + + ddr_type = LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_MASK; + + SIM_FEEDBACK0(200U + ddr_training_state); + SIM_FEEDBACK1(0U); + + switch (ddr_training_state) + { + case DDR_TRAINING_INIT: + tip_cfg_params = LIBERO_SETTING_TIP_CFG_PARAMS; + dpc_bits = LIBERO_SETTING_DPC_BITS ; + write_latency = LIBERO_SETTING_CFG_WRITE_LATENCY_SET; +#if (TUNE_RPC_166_VALUE == 1) + rpc_166_fifo_offset = DEFAULT_RPC_166_VALUE; +#endif +#ifdef MANUAL_ADDCMD_TRAINIG + refclk_offset = LIBERO_SETTING_MAX_MANUAL_REF_CLK_PHASE_OFFSET + 1U; +#endif +#ifdef SWEEP_ENABLED + sweep_state = INIT_SWEEP; +#endif + ddr_error_count = 0U; + error = 0U; + memfill((uint8_t *)&calib_data,0U,sizeof(calib_data)); + retry_count = 0U; +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r Start training. TIP_CFG_PARAMS:"\ + , LIBERO_SETTING_TIP_CFG_PARAMS); +#endif +#ifdef SWEEP_ENABLED + addr_cmd_value = LIBERO_SETTING_TIP_CFG_PARAMS\ + & ADDRESS_CMD_OFFSETT_MASK; + bclk_sclk_offset_value = (LIBERO_SETTING_TIP_CFG_PARAMS\ + & BCLK_SCLK_OFFSET_MASK)>>BCLK_SCLK_OFFSET_SHIFT; + dpc_vrgen_v_value = (LIBERO_SETTING_DPC_BITS & \ + BCLK_DPC_VRGEN_V_MASK)>>BCLK_DPC_VRGEN_V_SHIFT; + dpc_vrgen_h_value = (LIBERO_SETTING_DPC_BITS & \ + BCLK_DPC_VRGEN_H_MASK)>>BCLK_DPC_VRGEN_H_SHIFT; + dpc_vrgen_vs_value = (LIBERO_SETTING_DPC_BITS & \ + BCLK_DPC_VRGEN_VS_MASK)>>BCLK_DPC_VRGEN_VS_SHIFT; +#endif + ddr_training_state = DDR_TRAINING_CHECK_FOR_OFFMODE; + break; + case DDR_TRAINING_FAIL_SM2_VERIFY: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r SM2_VERIFY: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_SM_VERIFY: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r SM_VERIFY: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_SM_DQ_DQS: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r SM_DQ_DQS: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_SM_RDGATE: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r SM_RDGATE: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_SM_WRLVL: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r SM_WRLVL: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_SM_ADDCMD: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r SM_ADDCMD: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_SM_BCLKSCLK: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r BCLKSCLK_SWY: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_BCLKSCLK_SW: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r BCLKSCLK_SW: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_FULL_32BIT_NC_CHECK: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r 32BIT_NC_CHECK: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_32BIT_CACHE_CHECK: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r 32BIT_CACHE_CHECK: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_MIN_LATENCY: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r MIN_LATENCY: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_START_CHECK: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r START_CHECK: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_PLL_LOCK: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r PLL LOCK FAIL: ",addr_cmd_value); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + break; + case DDR_TRAINING_FAIL_DDR_SANITY_CHECKS: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r DDR_SANITY_CHECKS FAIL: ",\ + addr_cmd_value); + ddr_training_state = DDR_TRAINING_FAIL; +#endif + break; + case DDR_SWEEP_AGAIN: + retry_count++; + last_sweep_status = CALIBRATION_PASSED; + #ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r DDR_SWEEP_AGAIN: ",\ + ddr_training_state); + #endif + ddr_training_state = DDR_CHECK_TRAINING_SWEEP; + break; + case DDR_TRAINING_FAIL: +#ifdef DEBUG_DDR_INIT + { + tip_register_status (g_debug_uart); + (void)uprint32(g_debug_uart, "\n\r ****************************************************", 0U); + + } +#endif + retry_count++; + if(last_sweep_status != CALIBRATION_SUCCESS) + { + last_sweep_status = CALIBRATION_FAILED; + } + #ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r DDR_TRAINING_FAIL: ",\ + ddr_training_state); + (void)uprint32(g_debug_uart, "\n\r Retry Count: ", retry_count); + #endif + ddr_training_state = DDR_CHECK_TRAINING_SWEEP; + break; + + case DDR_CHECK_TRAINING_SWEEP: + { +#ifdef SWEEP_ENABLED + /* first check if we are finished */ + if(last_sweep_status == CALIBRATION_SUCCESS) + { + /* + * Try again with calculated values + */ + ddr_training_state = DDR_TRAINING_CHECK_FOR_OFFMODE; + } + else if(retry_count == TOTAL_SWEEPS) + { + sweep_index index; +#ifdef DEBUG_DDR_INIT + sweep_status(g_debug_uart); +#endif + /* + * Choose the best index + */ + if (get_best_sweep(&index) == 0U) + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r sweep success: ",\ + tip_cfg_params); +#endif + last_sweep_status = CALIBRATION_SUCCESS; + /* + * Use obtained settings + */ + addr_cmd_value = index.cmd_index +\ + LIBERO_SETTING_MIN_ADDRESS_CMD_OFFSET; + bclk_sclk_offset_value = index.bclk_sclk_index +\ + LIBERO_SETTING_MIN_ADDRESS_BCLK_SCLK_OFFSET; + dpc_vrgen_v_value = index.dpc_vgen_index +\ + LIBERO_SETTING_MIN_DPC_V_GEN; + dpc_vrgen_h_value = index.dpc_vgen_h_index +\ + LIBERO_SETTING_MIN_DPC_H_GEN; + dpc_vrgen_vs_value = index.dpc_vgen_vs_index +\ + LIBERO_SETTING_MIN_DPC_VS_GEN; + + tip_cfg_params = ((tip_cfg_params &\ + (~BCLK_SCLK_OFFSET_MASK))|\ + (bclk_sclk_offset_value<<BCLK_SCLK_OFFSET_SHIFT)); + tip_cfg_params = ((tip_cfg_params &\ + (~ADDRESS_CMD_OFFSETT_MASK))|(addr_cmd_value)); + dpc_bits = ((dpc_bits &\ + (~BCLK_DPC_VRGEN_V_MASK))|\ + (dpc_vrgen_v_value<<BCLK_DPC_VRGEN_V_SHIFT)); + dpc_bits = ((dpc_bits &\ + (~BCLK_DPC_VRGEN_H_MASK))|\ + (dpc_vrgen_h_value<<BCLK_DPC_VRGEN_H_SHIFT)); + dpc_bits = ((dpc_bits &\ + (~BCLK_DPC_VRGEN_VS_MASK))|\ + (dpc_vrgen_vs_value<<BCLK_DPC_VRGEN_VS_SHIFT)); + ddr_training_state = DDR_TRAINING_CHECK_FOR_OFFMODE; + } + else + { +#ifdef SWEEP_ENABLED + sweep_state = INIT_SWEEP; +#endif + retry_count = 0U; + ddr_training_state = DDR_TRAINING_SWEEP; + } + } + else + { + ddr_training_state = DDR_TRAINING_SWEEP; + } + ddr_error_count = 0U; + error = 0U; + memfill((uint8_t *)&calib_data,0U,sizeof(calib_data)); + DDRCFG->DFI.PHY_DFI_INIT_START.PHY_DFI_INIT_START = 0x0U; + /* reset controller */ + DDRCFG->MC_BASE2.CTRLR_INIT.CTRLR_INIT = 0x0U; + CFG_DDR_SGMII_PHY->training_start.training_start = 0x0U; + } +#else /* we are not SWEEP_ENABLED */ + ddr_error_count = 0U; + error = 0U; + memfill((uint8_t *)&calib_data,0U,sizeof(calib_data)); + DDRCFG->DFI.PHY_DFI_INIT_START.PHY_DFI_INIT_START = 0x0U; + /* reset controller */ + DDRCFG->MC_BASE2.CTRLR_INIT.CTRLR_INIT = 0x0U; + CFG_DDR_SGMII_PHY->training_start.training_start = 0x0U; + + ddr_training_state = DDR_TRAINING_CHECK_FOR_OFFMODE; + } +#endif + break; + + case DDR_TRAINING_SWEEP: +#ifdef SWEEP_ENABLED + { + static uint32_t sweep_count_cmd_offset; + static uint32_t sweep_count_bck_sclk; + static uint32_t sweep_count_dpc_v_bits; + static uint32_t sweep_count_dpc_h_bits; + static uint32_t sweep_count_dpc_vs_bits; + + switch(sweep_state) + { + case INIT_SWEEP: + /* + * Parameter values + */ + addr_cmd_value = LIBERO_SETTING_MIN_ADDRESS_CMD_OFFSET; + bclk_sclk_offset_value =\ + LIBERO_SETTING_MIN_ADDRESS_BCLK_SCLK_OFFSET; + dpc_vrgen_v_value = LIBERO_SETTING_MIN_DPC_V_GEN; + dpc_vrgen_h_value = LIBERO_SETTING_MIN_DPC_H_GEN; + dpc_vrgen_vs_value = LIBERO_SETTING_MIN_DPC_VS_GEN; + /* + * state counts + */ + sweep_count_cmd_offset = 0U; + sweep_count_bck_sclk = 0U; + sweep_count_dpc_v_bits = 0U; + sweep_count_dpc_h_bits = 0U; + sweep_count_dpc_vs_bits = 0U; + sweep_state = ADDR_CMD_OFFSET_SWEEP; + __attribute__((fallthrough)); /* deliberately fall through */ + case ADDR_CMD_OFFSET_SWEEP: + /* + * Record sweep result + */ + sweep_results[sweep_count_dpc_vs_bits][sweep_count_dpc_h_bits][sweep_count_dpc_v_bits]\ + [sweep_count_bck_sclk]\ + [sweep_count_cmd_offset] = last_sweep_status; + /* + * sweep: ADDR_CMD OFFSET + */ + addr_cmd_value++; + if (addr_cmd_value > \ + LIBERO_SETTING_MAX_ADDRESS_CMD_OFFSET) + { + addr_cmd_value = \ + LIBERO_SETTING_MIN_ADDRESS_CMD_OFFSET; + } + + tip_cfg_params = ((tip_cfg_params &\ + (~ADDRESS_CMD_OFFSETT_MASK))|(addr_cmd_value)); + sweep_count_cmd_offset++; + if(sweep_count_cmd_offset > MAX_NUMBER_ADDR_CMD_OFFSET_SWEEPS) + { + sweep_count_cmd_offset = 0U; + sweep_state = BCLK_SCLK_OFFSET_SWEEP; + } + else + { + /* + * Now do a sweep + */ + ddr_error_count = 0U; + error = 0U; + memfill((uint8_t *)&calib_data,0U,sizeof(calib_data)); + DDRCFG->DFI.PHY_DFI_INIT_START.PHY_DFI_INIT_START = 0x00000000U; + /* reset controller */ + DDRCFG->MC_BASE2.CTRLR_INIT.CTRLR_INIT = 0x00000000U; + CFG_DDR_SGMII_PHY->training_start.training_start = 0x00000000U; + ddr_training_state = DDR_TRAINING_CHECK_FOR_OFFMODE; + } + break; + case BCLK_SCLK_OFFSET_SWEEP: + /* + * sweep: BCLK_SCLK + */ + bclk_sclk_offset_value++; + if (bclk_sclk_offset_value > \ + LIBERO_SETTING_MAX_ADDRESS_BCLK_SCLK_OFFSET) + { + bclk_sclk_offset_value = \ + LIBERO_SETTING_MIN_ADDRESS_BCLK_SCLK_OFFSET; + } + tip_cfg_params = ((tip_cfg_params &\ + (~BCLK_SCLK_OFFSET_MASK))|\ + (bclk_sclk_offset_value<<BCLK_SCLK_OFFSET_SHIFT)); + sweep_count_bck_sclk++; + if(sweep_count_bck_sclk > MAX_NUMBER__BCLK_SCLK_OFFSET_SWEEPS) + { + sweep_count_bck_sclk = 0U; + sweep_state = DPC_VRGEN_V_SWEEP; + } + else + { + sweep_state = ADDR_CMD_OFFSET_SWEEP; + } + break; + case DPC_VRGEN_V_SWEEP: + /* + * sweep: DPC_VRGEN_V [4:6] + * LIBERO_SETTING_DPC_BITS + */ + dpc_vrgen_v_value++; + if (dpc_vrgen_v_value > \ + LIBERO_SETTING_MAX_DPC_V_GEN) + { + dpc_vrgen_v_value = \ + LIBERO_SETTING_MIN_DPC_V_GEN; + } + dpc_bits = ((dpc_bits &\ + (~BCLK_DPC_VRGEN_V_MASK))|\ + (dpc_vrgen_v_value<<BCLK_DPC_VRGEN_V_SHIFT)); + sweep_count_dpc_v_bits++; + if(sweep_count_dpc_v_bits > MAX_NUMBER_DPC_V_GEN_SWEEPS) + { + sweep_count_dpc_v_bits = 0U; + sweep_state = DPC_VRGEN_H_SWEEP; + } + else + { + sweep_state = BCLK_SCLK_OFFSET_SWEEP; + } + break; + case DPC_VRGEN_H_SWEEP: + /* + * sweep: DPC_VRGEN_V [4:6] + * LIBERO_SETTING_DPC_BITS + */ + dpc_vrgen_h_value++; + if (dpc_vrgen_h_value > \ + LIBERO_SETTING_MAX_DPC_H_GEN) + { + dpc_vrgen_h_value = \ + LIBERO_SETTING_MIN_DPC_H_GEN; + } + dpc_bits = ((dpc_bits &\ + (~BCLK_DPC_VRGEN_H_MASK))|\ + (dpc_vrgen_h_value<<BCLK_DPC_VRGEN_H_SHIFT)); + sweep_count_dpc_h_bits++; + if(sweep_count_dpc_h_bits > MAX_NUMBER_DPC_H_GEN_SWEEPS) + { + sweep_count_dpc_h_bits = 0U; + sweep_state = DPC_VRGEN_VS_SWEEP; + } + else + { + sweep_state = DPC_VRGEN_V_SWEEP; + } + break; + case DPC_VRGEN_VS_SWEEP: + /* + * sweep: DPC_VRGEN_V [4:6] + * LIBERO_SETTING_DPC_BITS + */ + dpc_vrgen_vs_value++; + if (dpc_vrgen_vs_value > \ + LIBERO_SETTING_MAX_DPC_VS_GEN) + { + dpc_vrgen_vs_value = \ + LIBERO_SETTING_MIN_DPC_VS_GEN; + } + dpc_bits = ((dpc_bits &\ + (~BCLK_DPC_VRGEN_VS_MASK))|\ + (dpc_vrgen_vs_value<<BCLK_DPC_VRGEN_VS_SHIFT)); + sweep_count_dpc_vs_bits++; + if(sweep_count_dpc_vs_bits > MAX_NUMBER_DPC_VS_GEN_SWEEPS) + { + sweep_count_dpc_vs_bits = 0U; + } + sweep_state = DPC_VRGEN_H_SWEEP; + break; + case FINISHED_SWEEP: + break; + default: + break; + } + } +#endif /* SWEEP_ENABLED */ + break; + + case DDR_TRAINING_CHECK_FOR_OFFMODE: + /* + * check if we are in off mode + */ + if (ddr_type == DDR_OFF_MODE) + { + ddr_off_mode(); + ret_status |= DDR_SETUP_DONE; + return (ret_status); + } + else + { + /* + * set initial conditions + */ + /* enable fabric noise */ +#ifdef FABRIC_NOISE_TEST + if(fabric_noise_en) + { + SYSREG->SOFT_RESET_CR &= 0x00U; + SYSREG->SUBBLK_CLOCK_CR = 0xffffffffUL; + SYSREG->GPIO_INTERRUPT_FAB_CR = 0x00000000UL; + PLIC_init(); + PLIC_SetPriority_Threshold(0); + __enable_irq(); + /* bit0-bit15 used to enable noise logic in steps of 5% + bit 16 noise logic reset + bit 17 clkmux sel + bit 18 pll powerdown + bit 19 external io enable for GCLKINT */ + PLIC_SetPriority(GPIO0_BIT0_or_GPIO2_BIT0_PLIC_0, 4U); + PLIC_SetPriority(GPIO0_BIT1_or_GPIO2_BIT1_PLIC_1, 4U); + PLIC_SetPriority(GPIO0_BIT2_or_GPIO2_BIT2_PLIC_2, 4U); + PLIC_SetPriority(GPIO0_BIT3_or_GPIO2_BIT3_PLIC_3, 4U); + PLIC_SetPriority(GPIO0_BIT4_or_GPIO2_BIT4_PLIC_4, 4U); + PLIC_SetPriority(GPIO0_BIT5_or_GPIO2_BIT5_PLIC_5, 4U); + PLIC_SetPriority(GPIO0_BIT6_or_GPIO2_BIT6_PLIC_6, 4U); + PLIC_SetPriority(GPIO0_BIT7_or_GPIO2_BIT7_PLIC_7, 4U); + PLIC_SetPriority(GPIO0_BIT8_or_GPIO2_BIT8_PLIC_8, 4U); + PLIC_SetPriority(GPIO0_BIT9_or_GPIO2_BIT9_PLIC_9, 4U); + PLIC_SetPriority(GPIO0_BIT10_or_GPIO2_BIT10_PLIC_10, 4U); + PLIC_SetPriority(GPIO0_BIT11_or_GPIO2_BIT11_PLIC_11, 4U); + PLIC_SetPriority(GPIO0_BIT12_or_GPIO2_BIT12_PLIC_12, 4U); + PLIC_SetPriority(GPIO0_BIT13_or_GPIO2_BIT13_PLIC_13, 4U); + PLIC_SetPriority(GPIO1_BIT0_or_GPIO2_BIT14_PLIC_14, 4U); + PLIC_SetPriority(GPIO1_BIT1_or_GPIO2_BIT15_PLIC_15, 4U); + PLIC_SetPriority(GPIO1_BIT2_or_GPIO2_BIT16_PLIC_16, 4U); + PLIC_SetPriority(GPIO1_BIT3_or_GPIO2_BIT17_PLIC_17, 4U); + PLIC_SetPriority(GPIO1_BIT4_or_GPIO2_BIT18_PLIC_18, 4U); + PLIC_SetPriority(GPIO1_BIT5_or_GPIO2_BIT19_PLIC_19, 4U); + + MSS_GPIO_init(GPIO2_LO); + MSS_GPIO_config_all(GPIO2_LO, MSS_GPIO_OUTPUT_MODE); + MSS_GPIO_set_outputs(GPIO2_LO, 0x00000UL); /* bits 15:0 - 0, noise logic disabled */ + delay(100); + /*MSS_GPIO_set_outputs(GPIO2_LO, 0x00FFFUL);*/ /* bits 12:0 - 1, 56% enabled */ + noise_ena = (1 << num_of_noise_blocks_en) - 1; + MSS_GPIO_set_outputs(GPIO2_LO, noise_ena); /* num_of_noise_blocks_en * 4.72% */ + fabric_noise_en = 0; + } +#endif /* FABRIC_NOISE_TEST */ + write_latency = MIN_LATENCY; + ddr_training_state = DDR_TRAINING_SET_MODE_VS_BITS; + } + break; + + case DDR_TRAINING_SET_MODE_VS_BITS: +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r dpc_bits: ",\ + dpc_bits); +#endif + /* + * Set the training mode + */ + set_ddr_mode_reg_and_vs_bits(dpc_bits); + ddr_training_state = DDR_TRAINING_FLASH_REGS; + break; + + case DDR_TRAINING_FLASH_REGS: + /* + * flash registers with RPC values + * Enable DDR IO decoders + * Note : + * rpc sequence: + * power-up -> mss_boot -> re-flash nv_map -> override + * any changes (to fix issues) + * + * SOFT_RESET_ bit 0 == periph soft reset, auto cleared + */ + CFG_DDR_SGMII_PHY->SOFT_RESET_DECODER_DRIVER.SOFT_RESET_DECODER_DRIVER = 1U; + CFG_DDR_SGMII_PHY->SOFT_RESET_DECODER_ODT.SOFT_RESET_DECODER_ODT=1U; + CFG_DDR_SGMII_PHY->SOFT_RESET_DECODER_IO.SOFT_RESET_DECODER_IO = 1U; + ddr_training_state = DDR_TRAINING_CORRECT_RPC; + break; + + case DDR_TRAINING_CORRECT_RPC: + /* + * correct some rpc registers, which were incorrectly set in mode + * setting + */ + set_ddr_rpc_regs(ddr_type); + ddr_training_state = DDR_TRAINING_SOFT_RESET; + break; + case DDR_TRAINING_SOFT_RESET: + /* + * Set soft reset on IP to load RPC to SCB regs (dynamic mode) + * Bring the DDR bank controller out of reset + */ + IOSCB_BANKCONT_DDR->soft_reset = 1U; /* DPC_BITS NV_MAP reset */ + ddr_training_state = DDR_TRAINING_CALIBRATE_IO; + break; + case DDR_TRAINING_CALIBRATE_IO: + /* + * Calibrate DDR I/O here, once all RPC settings correct + */ + ddr_pvt_calibration(); +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r PCODE = ",\ + (CFG_DDR_SGMII_PHY->IOC_REG2.IOC_REG2 & 0x7FU)); + (void)uprint32(g_debug_uart, "\n\r NCODE = ", \ + (((CFG_DDR_SGMII_PHY->IOC_REG2.IOC_REG2) >> 7U) & 0x7FU)); + (void)uprint32(g_debug_uart, "\n\r addr_cmd_value: ",\ + addr_cmd_value); + (void)uprint32(g_debug_uart, "\n\r bclk_sclk_offset_value: ",\ + bclk_sclk_offset_value); + (void)uprint32(g_debug_uart, "\n\r dpc_vrgen_v_value: ",\ + dpc_vrgen_v_value); + (void)uprint32(g_debug_uart, "\n\r dpc_vrgen_h_value: ",\ + dpc_vrgen_h_value); + (void)uprint32(g_debug_uart, "\n\r dpc_vrgen_vs_value: ",\ + dpc_vrgen_vs_value); +#endif + ddr_training_state = DDR_TRAINING_CONFIG_PLL; + break; + case DDR_TRAINING_CONFIG_PLL: + /* + * Configure the DDR PLL + */ + ddr_pll_config(SCB_UPDATE); + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_VERIFY_PLL_LOCK; + break; + case DDR_TRAINING_VERIFY_PLL_LOCK: + /* + * Verify DDR PLL lock + */ + if (ddr_pll_lock_scb() == 0U) + { + ddr_training_state = DDR_TRAINING_SETUP_SEGS; + } + else if(--timeout == 0U) + { + ddr_training_state = DDR_TRAINING_FAIL_PLL_LOCK; + } + break; + case DDR_TRAINING_SETUP_SEGS: + /* + * Configure Segments- address mapping, CFG0/CFG1 + */ + setup_ddr_segments(DEFAULT_SEG_SETUP); + /* + * enable the DDRC + */ + /* Turn on DDRC clock */ + SYSREG->SUBBLK_CLOCK_CR |= SUBBLK_CLOCK_CR_DDRC_MASK; + /* Remove soft reset */ + SYSREG->SOFT_RESET_CR &= (uint32_t)~SOFT_RESET_CR_DDRC_MASK; + ddr_training_state = DDR_TRAINING_SETUP_DDRC; + break; + case DDR_TRAINING_SETUP_DDRC: + /* + * set-up DDRC + * Configuration taken from the user. + */ + { + init_ddrc(); + ddr_training_state = DDR_TRAINING_RESET; + } + break; + case DDR_TRAINING_RESET: + /* + * Assert training reset + * reset pin is bit [1] + * and load skip setting + */ + /* leave in reset */ +/* To verify if separate reset required for DDR4 - believe it is not */ +#ifndef SPECIAL_TRAINIG_RESET + CFG_DDR_SGMII_PHY->training_reset.training_reset = 0x00000002U; +#ifndef SOFT_RESET_PRE_TAG_172 + DDRCFG->MC_BASE2.CTRLR_SOFT_RESET_N.CTRLR_SOFT_RESET_N =\ + 0x00000000U; + DDRCFG->MC_BASE2.CTRLR_SOFT_RESET_N.CTRLR_SOFT_RESET_N =\ + 0x00000001U; +#endif /* !SOFT_RESET_PRE_TAG_172 */ +#else + /* Disable CKE */ + DDRCFG->MC_BASE2.INIT_DISABLE_CKE.INIT_DISABLE_CKE = 0x1; + + /* Assert FORCE_RESET */ + DDRCFG->MC_BASE2.INIT_FORCE_RESET.INIT_FORCE_RESET = 0x1; + delay(100); + /* release reset to memory here, set INIT_FORCE_RESET to 0 */ + DDRCFG->MC_BASE2.INIT_FORCE_RESET.INIT_FORCE_RESET = 0x0; + delay(500000); + + /* Enable CKE */ + DDRCFG->MC_BASE2.INIT_DISABLE_CKE.INIT_DISABLE_CKE = 0x0; + delay(1000); + + /* reset pin is bit [1] */ + CFG_DDR_SGMII_PHY->training_reset.training_reset = 0x00000002U; + +#endif + ddr_training_state = DDR_TRAINING_ROTATE_CLK; + break; + case DDR_TRAINING_ROTATE_CLK: + /* + * Rotate bclk90 by 90 deg + */ + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt = 0x00000004U; + /*expert mode enabling */ + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x00000002U; + /* */ + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x7CU; /* loading */ + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x78U; + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x78U; + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x7CU; + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x4U; + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x64U; + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x66U; /* increment */ + for (uint32_t d=0;d< \ + LIBERO_SETTING_TIP_CONFIG_PARAMS_BCLK_VCOPHS_OFFSET;d++) + { + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x67U; + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x66U; + } + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x64U; + CFG_DDR_SGMII_PHY->expert_pllcnt.expert_pllcnt= 0x4U; + + /* setting load delay lines */ + CFG_DDR_SGMII_PHY->expert_dlycnt_mv_rd_dly_reg.expert_dlycnt_mv_rd_dly_reg\ + = 0x1FU; + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0xFFFFFFFFU; /* setting to 1 to load delaylines */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0x00000000U; + + /* write w DFICFG_REG mv_rd_dly 0x00000000 # + tip_apb_write(12'h89C, 32'h0); mv_rd_dly */ + CFG_DDR_SGMII_PHY->expert_dlycnt_mv_rd_dly_reg.expert_dlycnt_mv_rd_dly_reg \ + = 0x0U; + + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0xFFFFFFFFU; /* setting to 1 to load delaylines */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0x00000000U; + + + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause =\ + 0x0000003FU; + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause =\ + 0x00000000U; + + /* DQ */ + /* dfi_training_complete_shim = 1'b1 + dfi_wrlvl_en_shim = 1'b1 */ + CFG_DDR_SGMII_PHY->expert_dfi_status_override_to_shim.expert_dfi_status_override_to_shim = 0x6; + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg0.expert_dlycnt_load_reg0=\ + 0xFFFFFFFFU; /* load output delays */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0xF; /* (ECC) - load output delays */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg0.expert_dlycnt_load_reg0=\ + 0x0; /* clear */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0x0; /* (ECC) clear */ + + /* DQS + * dfi_wrlvl_en_shim = 1'b1 */ + CFG_DDR_SGMII_PHY->expert_dfi_status_override_to_shim.expert_dfi_status_override_to_shim = 0x4; + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg0.expert_dlycnt_load_reg0=\ + 0xFFFFFFFFU; /* load output delays */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0xF; /* (ECC) - load output delays */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg0.expert_dlycnt_load_reg0=\ + 0x0; /* clear */ + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1=\ + 0x0; /* (ECC) clear */ + + CFG_DDR_SGMII_PHY->expert_dfi_status_override_to_shim.expert_dfi_status_override_to_shim = 0x0; /* clear */ + + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause =\ + 0x0000003FU; + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause =\ + 0x00000000U; + + /* expert mode disabling */ + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en =\ + 0x00000000U; + ddr_training_state = DDR_TRAINING_SET_TRAINING_PARAMETERS; + break; + case DDR_TRAINING_SET_TRAINING_PARAMETERS: + /* + * SET TRAINING PARAMETERS + * + * TIP STATIC PARAMETERS 0 + * + * 30:22 Number of VCO Phase offsets between BCLK and SCLK + * 21:13 Number of VCO Phase offsets between BCLK and SCLK + * 12:6 Number of VCO Phase offsets between BCLK and SCLK + * 5:3 Number of VCO Phase offsets between BCLK and SCLK + * 2:0 Number of VCO Phase offsets between REFCLK and ADDCMD bits + */ + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r tip_cfg_params: ",\ + tip_cfg_params); +#endif + + CFG_DDR_SGMII_PHY->tip_cfg_params.tip_cfg_params =\ + tip_cfg_params; + timeout = 0xFFFF; + + if(use_software_bclk_sclk_training(ddr_type) == 1U) + { + /* + * Initiate software training + */ +#ifdef SOFT_RESET_PRE_TAG_172 + DDRCFG->MC_BASE2.CTRLR_SOFT_RESET_N.CTRLR_SOFT_RESET_N =\ + 0x00000001U; +#endif + ddr_training_state = DDR_TRAINING_IP_SM_BCLKSCLK_SW; + } + else + { + /* + * Initiate IP training and wait for dfi_init_complete + */ + /*asserting training_reset */ + if (ddr_type != DDR3) + { + CFG_DDR_SGMII_PHY->training_reset.training_reset =\ + 0x00000000U; + } + else + { + DDRCFG->MC_BASE2.CTRLR_SOFT_RESET_N.CTRLR_SOFT_RESET_N =\ + 0x00000001U; + } + ddr_training_state = DDR_TRAINING_IP_SM_START; + } + } + break; + + case DDR_TRAINING_IP_SM_BCLKSCLK_SW: + /* + * We have chosen to use software bclk sclk sweep instead of IP + */ + { + uint32_t bclk_phase, bclk90_phase,refclk_phase; + bclk_answer = 0U; + { + /* + * BEGIN MANUAL BCLKSCLK TRAINING + */ + uint32_t rx_previous=0x3U; + uint32_t rx_current=0U; + uint32_t answer_count[8U]={0U,0U,0U,0U,0U,0U,0U,0U}; + uint32_t answer_index=0U; + + /*UPPER LIMIT MUST BE MULTIPLE OF 8 */ + for (uint32_t i=0U; i<(8U * 100); i++) + { + + bclk_phase = ( i & 0x07UL ) << 8U; + bclk90_phase = ((i+2U) & 0x07UL ) << 11U; + /* + * LOAD BCLK90 PHASE + */ + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase); + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00000003UL | bclk_phase | bclk90_phase); + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase); + + /* + * No pause required, causes an issue + */ + + /* + * SAMPLE RX_BCLK + */ + rx_current = ((CFG_DDR_SGMII_PHY->expert_addcmd_ln_readback.expert_addcmd_ln_readback) >> 12)& 0x03; + /* IF WE FOUND A TRANSITION, BREAK THE LOOP */ + if ((rx_current & (~rx_previous)) != 0x00000000UL) + { + answer_index=i&0x07U; + /* increment the answer count for this index */ + answer_count[answer_index]++; + } + + rx_previous = rx_current; + uint32_t max=0U; + for (uint32_t j=0U;j<8U;j++) + { + /* sweep through found answers and select the most common */ + if (answer_count[j] > max) + { + bclk_answer = j; + max=answer_count[j]; + } + } + } + } + ddr_training_state = DDR_MANUAL_ADDCMD_TRAINING_SW; + break; + + case DDR_MANUAL_ADDCMD_TRAINING_SW: + { + /* + * APPLY OFFSET & LOAD THE PHASE + * bclk_sclk_offset_value + * BCLK_SCLK_OFFSET_BASE + */ + if(LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) + { + /* + * We are skipping add/cmd training so need to set + * refclk phase offset manually + * We may need to sweep this + */ + refclk_phase = (uint32_t)(((bclk_answer+SW_TRAING_BCLK_SCLK_OFFSET + 5U + LIBERO_SETTING_MANUAL_REF_CLK_PHASE_OFFSET ) & 0x07UL) << 2U); + bclk_phase = ((bclk_answer+SW_TRAING_BCLK_SCLK_OFFSET) & 0x07UL ) << 8U; + bclk90_phase= ((bclk_answer+SW_TRAING_BCLK_SCLK_OFFSET+2U) & 0x07UL ) << 11U; + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase | refclk_phase); + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00000003UL | bclk_phase | bclk90_phase | refclk_phase); + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase | refclk_phase); + } + else + { + bclk_phase = ((bclk_answer+SW_TRAING_BCLK_SCLK_OFFSET) & 0x07UL ) << 8U; + bclk90_phase=((bclk_answer+SW_TRAING_BCLK_SCLK_OFFSET+2U) & 0x07UL ) << 11U; + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase); + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00000003UL | bclk_phase | bclk90_phase); + MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase); + } + ddr_training_state = DDR_TRAINING_IP_SM_START; + /* END MANUAL BCLKSCLK TRAINING */ + } + } + if(--timeout == 0U) + { + ddr_training_state = DDR_TRAINING_FAIL_BCLKSCLK_SW; + } + break; + case DDR_TRAINING_IP_SM_START: + { + CFG_DDR_SGMII_PHY->training_skip.training_skip =\ + LIBERO_SETTING_TRAINING_SKIP_SETTING; + if ((ddr_type == DDR3)||(ddr_type == LPDDR4)||(ddr_type == DDR4)) + { + /* RX_MD_CLKN */ + CFG_DDR_SGMII_PHY->rpc168.rpc168 = 0x0U; + } +#ifdef DDR_TRAINING_IP_SM_START_DELAY + delay(100); +#endif + /* release reset to training */ + CFG_DDR_SGMII_PHY->training_reset.training_reset = 0x00000000U; +#ifdef IP_SM_START_TRAINING_PAUSE + /* todo: pause removed at Alister's request for test. Will + * remove once verified not required after further testing + */ + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0xffU; + delay(100); + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause = 0x00000000U; + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause = 0x0000003FU; + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause = 0x00000000U; + delay(100); + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x00U; + delay(100); +#endif + } + { + DDRCFG->DFI.PHY_DFI_INIT_START.PHY_DFI_INIT_START =\ + 0x00000000U; + /* kick off training- DDRC, set dfi_init_start */ + DDRCFG->DFI.PHY_DFI_INIT_START.PHY_DFI_INIT_START =\ + 0x00000001U; + DDRCFG->MC_BASE2.CTRLR_INIT.CTRLR_INIT = 0x00000000U; + DDRCFG->MC_BASE2.CTRLR_INIT.CTRLR_INIT = 0x00000001U; + + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_START_CHECK; + } +#ifdef DEBUG_DDR_INIT +#ifdef MANUAL_ADDCMD_TRAINIG + (void)uprint32(g_debug_uart, "\n\r\n\r ADDCMD_OFFSET ", refclk_offset); +#endif +#endif + break; + case DDR_TRAINING_IP_SM_START_CHECK: +#ifndef RENODE_DEBUG + if((DDRCFG->DFI.STAT_DFI_INIT_COMPLETE.STAT_DFI_INIT_COMPLETE\ + & 0x01U) == 0x01U) +#endif + { +#ifdef LANE_ALIGNMENT_RESET_REQUIRED + CFG_DDR_SGMII_PHY->lane_alignment_fifo_control.lane_alignment_fifo_control = 0x00U; + CFG_DDR_SGMII_PHY->lane_alignment_fifo_control.lane_alignment_fifo_control = 0x02U; +#endif + +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, \ + "\n\r\n\r pll_phadj_after_hw_training ",\ + MSS_SCB_DDR_PLL->PLL_DIV_2_3); + (void)uprint32(g_debug_uart, \ + "\n\r\n\r pll_phadj_after_hw_training ",\ + MSS_SCB_DDR_PLL->PLL_DIV_0_1); +#endif + + if(LIBERO_SETTING_TRAINING_SKIP_SETTING & BCLK_SCLK_BIT) + { + ddr_training_state = DDR_TRAINING_IP_SM_ADDCMD; + } + else + { + ddr_training_state = DDR_TRAINING_IP_SM_BCLKSCLK; + } + timeout = 0xFFFF; + } + if(--timeout == 0U) + { + ddr_training_state = DDR_TRAINING_FAIL_START_CHECK; + } + break; + case DDR_TRAINING_IP_SM_BCLKSCLK: + if(CFG_DDR_SGMII_PHY->training_status.training_status & BCLK_SCLK_BIT) + { + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_ADDCMD; + } + if(--timeout == 0U) + { + ddr_training_state = DDR_TRAINING_FAIL_SM_BCLKSCLK; + } + break; + + case DDR_TRAINING_IP_SM_ADDCMD: + if(LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) + { + timeout = 0xFFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_WRLVL; + } + else if(CFG_DDR_SGMII_PHY->training_status.training_status & ADDCMD_BIT) + { + timeout = 0xFFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_WRLVL; + } + if(--timeout == 0U) + { + /* + * Typically this can fail for two + * reasons: + * 1. ADD/CMD not being received + * We need to sweep: + * ADDCMD_OFFSET [0:3] RW value + * sweep-> 0x2 -> 4 -> C -> 0 + * 2. DQ not received + * We need to sweep: + * LIBERO_SETTING_DPC_BITS + * DPC_VRGEN_H [4:6] value= 0x8->0xC + * + * */ + ddr_training_state = DDR_TRAINING_FAIL_SM_ADDCMD; + } + break; + case DDR_TRAINING_IP_SM_WRLVL: + if(LIBERO_SETTING_TRAINING_SKIP_SETTING & WRLVL_BIT) + { + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_RDGATE; + } + else if(CFG_DDR_SGMII_PHY->training_status.training_status & WRLVL_BIT) + { + timeout = 0xFFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_RDGATE; + } + if(--timeout == 0U) + { + ddr_training_state = DDR_TRAINING_FAIL_SM_WRLVL; + } + break; + case DDR_TRAINING_IP_SM_RDGATE: + if(LIBERO_SETTING_TRAINING_SKIP_SETTING & RDGATE_BIT) + { + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_DQ_DQS; + } + else if(CFG_DDR_SGMII_PHY->training_status.training_status & RDGATE_BIT) + { + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_DQ_DQS; + } + if(--timeout == 0U) + { + ddr_training_state = DDR_TRAINING_FAIL_SM_RDGATE; + } + break; + case DDR_TRAINING_IP_SM_DQ_DQS: + if(LIBERO_SETTING_TRAINING_SKIP_SETTING & DQ_DQS_BIT) + { + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_VERIFY; + } + else if(CFG_DDR_SGMII_PHY->training_status.training_status & DQ_DQS_BIT) + { + timeout = 0xFFFF; + ddr_training_state = DDR_TRAINING_IP_SM_VERIFY; + } + if(--timeout == 0U) + { + ddr_training_state = DDR_TRAINING_FAIL_SM_DQ_DQS; + } + break; + + case DDR_TRAINING_IP_SM_VERIFY: + if ((DDRCFG->DFI.STAT_DFI_TRAINING_COMPLETE.STAT_DFI_TRAINING_COMPLETE & 0x01U) == 0x01U) + { + /* + * Step 15: + * check worked for each lane + */ + uint32_t lane_sel, t_status = 0U; + for (lane_sel=0U; lane_sel< \ + LIBERO_SETTING_DATA_LANES_USED; lane_sel++) + { + SIM_FEEDBACK1(1000U); + delay(10U); + SIM_FEEDBACK1(1001U); + CFG_DDR_SGMII_PHY->lane_select.lane_select =\ + lane_sel; + delay(10U); + /* + * verify cmd address results + * rejects if not acceptable + * */ + { + uint32_t ca_status[8]= {\ + ((CFG_DDR_SGMII_PHY->addcmd_status0.addcmd_status0)&0xFFU),\ + ((CFG_DDR_SGMII_PHY->addcmd_status0.addcmd_status0>>8U)&0xFFU), \ + ((CFG_DDR_SGMII_PHY->addcmd_status0.addcmd_status0>>16U)&0xFFU),\ + ((CFG_DDR_SGMII_PHY->addcmd_status0.addcmd_status0>>24U)&0xFFU),\ + ((CFG_DDR_SGMII_PHY->addcmd_status1.addcmd_status1)&0xFFU),\ + ((CFG_DDR_SGMII_PHY->addcmd_status1.addcmd_status1>>8U)&0xFFU),\ + ((CFG_DDR_SGMII_PHY->addcmd_status1.addcmd_status1>>16U)&0xFFU),\ + ((CFG_DDR_SGMII_PHY->addcmd_status1.addcmd_status1>>24U)&0xFFU)}; + uint32_t low_ca_dly_count = 0U; + uint32_t last = 0U; + uint32_t decrease_count = 0U; + for(uint32_t i =0U; i<8U;i++) + { + if(ca_status[i] < 5U) + { + low_ca_dly_count++; + } + if(ca_status[i]<=last) + { + decrease_count++; + } + last = ca_status[i]; + } + if(ca_status[0]<= ca_status[7U]) + { + decrease_count++; + } + if((LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) != ADDCMD_BIT) + { + /* Retrain if abnormal CA training result detected */ + if(low_ca_dly_count > ABNORMAL_RETRAIN_CA_DLY_DECREASE_COUNT) + { + t_status = t_status | 0x01U; + } + /* Retrain if abnormal CA training result detected */ + if(decrease_count > ABNORMAL_RETRAIN_CA_DECREASE_COUNT) + { + t_status = t_status | 0x01U; + } + } + } + /* Check that gate training passed without error */ + t_status =t_status |\ + CFG_DDR_SGMII_PHY->gt_err_comb.gt_err_comb; + delay(10U); + /* Check that DQ/DQS training passed without error */ + if(CFG_DDR_SGMII_PHY->dq_dqs_err_done.dq_dqs_err_done != 8U) + { + t_status = t_status | 0x01U; + } + /* Check that DQ/DQS calculated window is above 5 taps. */ + if(CFG_DDR_SGMII_PHY->dqdqs_status1.dqdqs_status1 < \ + DQ_DQS_NUM_TAPS) + { + t_status = t_status | 0x01U; + } +#ifdef DCT_EXTRA_CHECKS /* todo: Theses checks was added by DCT */ + if(((CFG_DDR_SGMII_PHY->gt_txdly.gt_txdly)&0xFFU) == 0U) // Gate training tx_dly check: AL + { + t_status = t_status | 0x01U; + } + if(((CFG_DDR_SGMII_PHY->gt_txdly.gt_txdly>>8U)&0xFFU) == 0U) + { + t_status = t_status | 0x01U; + } + if(((CFG_DDR_SGMII_PHY->gt_txdly.gt_txdly>>16U)&0xFFU) == 0U) + { + t_status = t_status | 0x01U; + } + if(((CFG_DDR_SGMII_PHY->gt_txdly.gt_txdly>>24U)&0xFFU) == 0U) + { + t_status = t_status | 0x01U; + } +#endif + } + #ifdef RENODE_DEBUG + t_status = 0U; /* Dummy success -move on to + next stage */ + #endif + if(t_status == 0U) + { + SIM_FEEDBACK1(21U); + /* + * We can now set vref on the memory + * mode register for lpddr4 + * May include other modes, and include a sweep + * Alister looking into this and will revert. + */ + if (ddr_type == LPDDR4) + { +#ifdef SET_VREF_LPDDR4_MODE_REGS + mode_register_write(DDR_MODE_REG_VREF,\ + DDR_MODE_REG_VREF_VALUE); +#endif + } + ddr_training_state = DDR_TRAINING_SET_FINAL_MODE; + } + else /* fail, try again */ + { + SIM_FEEDBACK1(20U); + ddr_training_state = DDR_TRAINING_FAIL_SM_VERIFY; + } + } + else + { + ddr_training_state = DDR_TRAINING_FAIL_SM2_VERIFY; + } + break; + + + case DDR_TRAINING_SET_FINAL_MODE: + /* + * Set final mode register value. + */ + CFG_DDR_SGMII_PHY->DDRPHY_MODE.DDRPHY_MODE =\ + LIBERO_SETTING_DDRPHY_MODE; +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r DDR FINAL_MODE: ",\ + LIBERO_SETTING_DDRPHY_MODE); +#ifdef DEBUG_DDR_CFG_DDR_SGMII_PHY + (void)print_reg_array(g_debug_uart , + (uint32_t *)CFG_DDR_SGMII_PHY,\ + (sizeof(CFG_DDR_SGMII_PHY_TypeDef)/4U)); +#endif +#ifdef DEBUG_DDR_DDRCFG + debug_read_ddrcfg(); +#endif +#endif +#ifdef DEBUG_DDR_INIT + { + tip_register_status (g_debug_uart); + (void)uprint32(g_debug_uart, "\n\r ****************************************************", 0U); + + } +#endif + ddr_training_state = DDR_TRAINING_WRITE_CALIBRATION; + break; + + case DDR_TRAINING_WRITE_CALIBRATION: + /* + * Does the following in the DDRC need to be checked?? + * DDRCFG->DFI.STAT_DFI_TRAINING_COMPLETE.STAT_DFI_TRAINING_COMPLETE; + * + */ + number_of_lanes_to_calibrate = get_num_lanes(); + /* + * Now start the write calibration as training has been successful + */ + if(error == 0U) + { + if (ddr_type == LPDDR4) + { + uint8_t lane; + /* Changed default value to centre dq/dqs on window */ + CFG_DDR_SGMII_PHY->rpc220.rpc220 = 0xCUL; + for(lane = 0U; lane < number_of_lanes_to_calibrate; lane++) + { + load_dq(lane); + } + SIM_FEEDBACK1(1U); + +#ifdef SW_CONFIG_LPDDR_WR_CALIB_FN + error =\ + write_calibration_lpddr4_using_mtc(\ + number_of_lanes_to_calibrate); +#else + error =\ + write_calibration_using_mtc(\ + number_of_lanes_to_calibrate); +#endif + } + else + { + SIM_FEEDBACK1(2U); + error =\ + write_calibration_using_mtc(number_of_lanes_to_calibrate); + } + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(106U); + } + } +#if (EN_RETRY_ON_FIRST_TRAIN_PASS == 1) + if((error == 0U)&&(retry_count != 0U)) +#else + if(error == 0U) +#endif + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r wr calib result ",\ + calib_data.write_cal.lane_calib_result); +#endif + ddr_training_state = DDR_SWEEP_CHECK; + } + else if(error == MTC_TIMEOUT_ERROR) + { + error = 0U; + ddr_training_state = DDR_TRAINING_FAIL_DDR_SANITY_CHECKS; + } + else + { + error = 0U; + ddr_training_state = DDR_TRAINING_WRITE_CALIBRATION_RETRY; + } + break; + + case DDR_TRAINING_WRITE_CALIBRATION_RETRY: + /* + * Clear write calibration data + */ + memfill((uint8_t *)&calib_data,0U,sizeof(calib_data)); + /* + * Try the next offset + */ + write_latency++; + if (write_latency > MAX_LATENCY) + { + write_latency = MIN_LATENCY; + ddr_training_state = DDR_TRAINING_FAIL_MIN_LATENCY; + } + else + { + DDRCFG->DFI.CFG_DFI_T_PHY_WRLAT.CFG_DFI_T_PHY_WRLAT =\ + write_latency; +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r wr write latency ",\ + write_latency); +#endif + ddr_training_state = DDR_TRAINING_WRITE_CALIBRATION; + } + break; + + case DDR_SWEEP_CHECK: +#ifdef SWEEP_ENABLED + if((retry_count != 0U)&&(retry_count < (TOTAL_SWEEPS-1U))) + { + ddr_training_state = DDR_SWEEP_AGAIN; + } + else +#endif + { + ddr_training_state = DDR_SANITY_CHECKS; + } + break; + + case DDR_SANITY_CHECKS: + /* + * Now start the write calibration if training successful + */ +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r DDR SANITY_CHECKS: ",\ + error); +#endif + if(error == 0U) + { +#ifdef DDR_SANITY_CHECKS_EN + error = memory_tests(); +#endif + } + if(error == 0U) + { + ddr_training_state = DDR_FULL_MTC_CHECK; + } + else + { + ddr_training_state = DDR_TRAINING_FAIL_DDR_SANITY_CHECKS; + } + break; + + case DDR_FULL_MTC_CHECK: + { + uint64_t start_address = 0x0000000000000000ULL; + uint32_t size = ONE_MB_MTC; /* Number of reads for each iteration 2**size*/ + uint8_t mask; + if (get_num_lanes() <= 3U) + { + mask = 0x3U; + } + else + { + mask = 0xFU; + } + error = MTC_test(mask, start_address, size, MTC_COUNTING_PATTERN, MTC_ADD_SEQUENTIAL, &error); + /* Read using different patterns */ + error = 0U; + error |= MTC_test(mask, start_address, size, MTC_COUNTING_PATTERN, MTC_ADD_SEQUENTIAL, &error); + error |= MTC_test(mask, start_address, size, MTC_WALKING_ONE, MTC_ADD_SEQUENTIAL, &error); + error |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM, MTC_ADD_SEQUENTIAL, &error); + error |= MTC_test(mask, start_address, size, MTC_NO_REPEATING_PSEUDO_RANDOM, MTC_ADD_SEQUENTIAL, &error); + error |= MTC_test(mask, start_address, size, MTC_ALT_ONES_ZEROS, MTC_ADD_SEQUENTIAL, &error); + error |= MTC_test(mask, start_address, size, MTC_ALT_5_A, MTC_ADD_SEQUENTIAL, &error); + error |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM_16BIT, MTC_ADD_SEQUENTIAL, &error); + error |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM_8BIT, MTC_ADD_SEQUENTIAL, &error); + + error |= MTC_test(mask, start_address, size, MTC_COUNTING_PATTERN, MTC_ADD_RANDOM, &error); + error |= MTC_test(mask, start_address, size, MTC_WALKING_ONE, MTC_ADD_RANDOM, &error); + error |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM, MTC_ADD_RANDOM, &error); + error |= MTC_test(mask, start_address, size, MTC_NO_REPEATING_PSEUDO_RANDOM, MTC_ADD_RANDOM, &error); + error |= MTC_test(mask, start_address, size, MTC_ALT_ONES_ZEROS, MTC_ADD_RANDOM, &error); + error |= MTC_test(mask, start_address, size, MTC_ALT_5_A, MTC_ADD_RANDOM, &error); + error |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM_16BIT, MTC_ADD_RANDOM, &error); + error |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM_8BIT, MTC_ADD_RANDOM, &error); + } + if(error == 0U) + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r Passed MTC full check ", error); +#endif + ddr_training_state = DDR_FULL_32BIT_NC_CHECK; + } + else + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r Failed MTC full check ", error); +#endif + ddr_training_state = DDR_TRAINING_FAIL; + } + break; + + case DDR_FULL_32BIT_NC_CHECK: + /* + * write and read back test from drr, non cached access + */ + { +#if (DDR_FULL_32BIT_NC_CHECK_EN == 1) + error = ddr_read_write_fn((uint64_t*)LIBERO_SETTING_DDR_32_NON_CACHE,\ + SW_CFG_NUM_READS_WRITES,\ + SW_CONFIG_PATTERN); +#endif + } + if(error == 0U) + { + ddr_training_state = DDR_FULL_32BIT_CACHE_CHECK; + } + else + { + ddr_training_state = DDR_TRAINING_FAIL_FULL_32BIT_NC_CHECK; + } + break; + case DDR_FULL_32BIT_CACHE_CHECK: +#if (DDR_FULL_32BIT_CACHED_CHECK_EN == 1) + error = ddr_read_write_fn((uint64_t*)LIBERO_SETTING_DDR_32_CACHE,\ + SW_CFG_NUM_READS_WRITES,\ + SW_CONFIG_PATTERN); +#endif + if(error == 0U) + { +#ifdef SKIP_VERIFY_PATTERN_IN_CACHE + ddr_training_state = DDR_FULL_32BIT_WRC_CHECK; +#else + ddr_training_state = DDR_LOAD_PATTERN_TO_CACHE; +#endif + } + else + { + ddr_training_state = DDR_TRAINING_FAIL_32BIT_CACHE_CHECK; + } + break; + case DDR_LOAD_PATTERN_TO_CACHE: + load_ddr_pattern(LIBERO_SETTING_DDR_32_CACHE, SIZE_OF_PATTERN_TEST, SIZE_OF_PATTERN_OFFSET); + if(error == 0U) + { + ddr_training_state = DDR_VERIFY_PATTERN_IN_CACHE; + } + else + { + ddr_training_state = DDR_TRAINING_FAIL; + } + break; + case DDR_VERIFY_PATTERN_IN_CACHE: + error = test_ddr(NO_PATTERN_IN_CACHE_READS, SIZE_OF_PATTERN_TEST); + if(error == 0U) + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r\n\r wr write latency ",\ + write_latency); +#if (TUNE_RPC_166_VALUE == 1) + (void)uprint32(g_debug_uart, "\n\r rpc_166_fifo_offset: ",\ + rpc_166_fifo_offset); +#endif +#endif + ddr_training_state = DDR_FULL_32BIT_WRC_CHECK; + } + else + { +#if (TUNE_RPC_166_VALUE == 1) + +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\r rpc_166_fifo_offset: ",\ + rpc_166_fifo_offset); +#endif + +#ifdef NOT_A_FULL_RETRAIN + + /* this fails post tests */ + if(num_rpc_166_retires < NUM_RPC_166_VALUES) + { + num_rpc_166_retires++; + rpc_166_fifo_offset++; + if(rpc_166_fifo_offset > MAX_RPC_166_VALUE) + { + rpc_166_fifo_offset = MIN_RPC_166_VALUE; + } + /* try again here DDR_LOAD_PATTERN_TO_CACHE */ + } + else + { + num_rpc_166_retires = 0U; + rpc_166_fifo_offset = DEFAULT_RPC_166_VALUE; + ddr_training_state = DDR_TRAINING_FAIL; + } + CFG_DDR_SGMII_PHY->rpc166.rpc166 = rpc_166_fifo_offset; + //PAUSE to reset fifo (loads new RXPTR value). + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x1U; + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause =\ + 0x0000003EU; + CFG_DDR_SGMII_PHY->expert_dlycnt_pause.expert_dlycnt_pause =\ + 0x00000000U; + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x8U; + //delay(10); + //END PAUSE +#else + if(num_rpc_166_retires < NUM_RPC_166_VALUES) + { + num_rpc_166_retires++; + rpc_166_fifo_offset++; + if(rpc_166_fifo_offset > MAX_RPC_166_VALUE) + { + rpc_166_fifo_offset = MIN_RPC_166_VALUE; + } + /* try again here DDR_LOAD_PATTERN_TO_CACHE */ + } + else + { + num_rpc_166_retires = 0U; + rpc_166_fifo_offset = DEFAULT_RPC_166_VALUE; + ddr_training_state = DDR_TRAINING_FAIL; + } + ddr_training_state = DDR_TRAINING_FAIL; +#endif +#else /* (TUNE_RPC_166_VALUE == 0) */ + ddr_training_state = DDR_TRAINING_FAIL; +#endif + } + break; + case DDR_FULL_32BIT_WRC_CHECK: + if(error == 0U) + { + ddr_training_state = DDR_FULL_64BIT_NC_CHECK; + } + else + { + ddr_training_state = DDR_TRAINING_FAIL; + } + break; + case DDR_FULL_64BIT_NC_CHECK: + if(error == 0U) + { + ddr_training_state = DDR_FULL_64BIT_CACHE_CHECK; + } + else + { + ddr_training_state = DDR_TRAINING_FAIL; + } + break; + case DDR_FULL_64BIT_CACHE_CHECK: + if(error == 0U) + { + ddr_training_state = DDR_FULL_64BIT_WRC_CHECK; + } + else + { + ddr_training_state = DDR_TRAINING_FAIL; + } + break; + case DDR_FULL_64BIT_WRC_CHECK: + if(error == 0U) + { + ddr_training_state = DDR_TRAINING_VREFDQ_CALIB; + } + else + { + ddr_training_state = DDR_TRAINING_FAIL; + } + + break; + + case DDR_TRAINING_VREFDQ_CALIB: +#ifdef VREFDQ_CALIB + /* + * This step is optional + * todo: Test once initial board verification complete + */ + error = VREFDQ_calibration_using_mtc(); + if(error != 0U) + { + ddr_error_count++; + } +#endif + ddr_training_state = DDR_TRAINING_FPGA_VREFDQ_CALIB; + break; + + case DDR_TRAINING_FPGA_VREFDQ_CALIB: +#ifdef FPGA_VREFDQ_CALIB + /* + * This step is optional + * todo: Test once initial board verification complete + */ + error = FPGA_VREFDQ_calibration_using_mtc(); + if(error != 0U) + { + ddr_error_count++; + } +#endif + ddr_training_state = DDR_TRAINING_FINISH_CHECK; + break; + + case DDR_TRAINING_FINISH_CHECK: + /* + * return status + */ +#ifdef DEBUG_DDR_INIT + { + tip_register_status (g_debug_uart); + (void)uprint32(g_debug_uart, "\n\r\n\r DDR_TRAINING_PASS: ",\ + ddr_training_state); + (void)uprint32(g_debug_uart, "\n ****************************************************", 0); + + } +#endif + if(ddr_error_count > 0) + { + ret_status |= DDR_SETUP_FAIL; + } + else + { + /* + * Configure Segments- address mapping, CFG0/CFG1 + */ + setup_ddr_segments(LIBERO_SEG_SETUP); + } + ret_status |= DDR_SETUP_DONE; + ddr_training_state = DDR_TRAINING_FINISHED; + break; + + default: + case DDR_TRAINING_FINISHED: + break; + } /* end of case statement */ + + return (ret_status); +} + + +/** + * get_num_lanes(void) + * @return number of lanes used, 2(16 bit), 3(16 bit + ecc), 4(32 bit) or 5 + * Note: Lane 4 always used when ECC enabled, even for x16 + */ +static uint8_t get_num_lanes(void) +{ + uint8_t lanes; + /* Check width, 16bit or 32bit bit supported, 1 => 32 bit */ + if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_BUS_WIDTH_MASK) ==\ + DDRPHY_MODE_BUS_WIDTH_4_LANE) + { + lanes = 4U; + } + else + { + lanes = 2U; + } + /* Check if using ECC, add a lane */ + if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_ECC_MASK) ==\ + DDRPHY_MODE_ECC_ON) + { + lanes++; + } + return lanes; +} + + + +/***************************************************************************//** + * set_ddr_mode_reg_and_vs_bits() + * + */ +static void set_ddr_mode_reg_and_vs_bits(uint32_t dpc_bits) +{ + DDR_TYPE ddr_type = LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_MASK; + /* + * R1.6 + * Write DDR phy mode reg (eg DDR3) + * When we write to the mode register, an ip state machine copies default + * values for the particular mode chosen to RPC registers associated with + * DDR in the MSS custom block. + * ( Note: VS bits are not include in the copy so we set below ) + * The RPC register values are transferred to the SCB registers in a + * subsequent step. + */ + /* + * Set VS bits + * Select VS bits for DDR mode selected --- set dynamic pc bit settings to + * allow editing of RPC registers + * pvt calibration etc + * + * [19] dpc_move_en_v enable dynamic control of vrgen circuit for + * ADDCMD pins + * [18] dpc_vrgen_en_v enable vref generator for ADDCMD pins + * [17:12] dpc_vrgen_v reference voltage ratio setting for ADDCMD + * pins + * [11:11] dpc_move_en_h enable dynamic control of vrgen circuit for + * DQ/DQS pins + * [10:10] dpc_vrgen_en_h enable vref generator for DQ/DQS pins + * [9:4] dpc_vrgen_h reference voltage ratio setting for DQ/DQS + * pins + * [3:0] dpc_vs bank voltage select for pvt calibration + */ + /* + DDRPHY_MODE setting from MSS configurator + DDRMODE :3; + ECC :1; + CRC :1; + Bus_width :3; + DMI_DBI :1; + DQ_drive :2; + DQS_drive :2; + ADD_CMD_drive :2; + Clock_out_drive :2; + DQ_termination :2; + DQS_termination :2; + ADD_CMD_input_pin_termination :2; + preset_odt_clk :2; + Power_down :1; + rank :1; + Command_Address_Pipe :2; + */ + { + if ((ddr_type == DDR4) &&\ + (LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_ECC_MASK) ==\ + DDRPHY_MODE_ECC_ON) + { + /* + * For ECC on when DDR4, and data mask on during training, training + * will not pass + * This will eventually be handled by the configurator + * DM will not be allowed for DDR4 with ECC + */ + CFG_DDR_SGMII_PHY->DDRPHY_MODE.DDRPHY_MODE =\ + (LIBERO_SETTING_DDRPHY_MODE & DMI_DBI_MASK ); + } + else + { + CFG_DDR_SGMII_PHY->DDRPHY_MODE.DDRPHY_MODE =\ + LIBERO_SETTING_DDRPHY_MODE; + } + delay((uint32_t) 100U); + CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS = dpc_bits; + } +} + + + +/***************************************************************************//** + * set_ddr_rpc_regs() + * @param ddr_type + */ +static void set_ddr_rpc_regs(DDR_TYPE ddr_type) +{ + /* + * Write DDR phy mode reg (eg DDR3) + * When we write to the mode register, an ip state machine copies default + * values for the particular mode chossen + * to RPC registers associated with DDR in the MSS custom block. + * The RPC register values are transferred to the SCB registers in a + * subsequent step. + * + * Question: + * Select VS bits (eg DDR3 ) (vs bits not included in mode setup - should + * be??) + * Small wait while state machine transfer takes place required here. + * (status bit required?) + * + */ + /* + DDRPHY_MODE setting from MSS configurator + DDRMODE :3; + ECC :1; + CRC :1; + Bus_width :3; + DMI_DBI :1; + DQ_drive :2; + DQS_drive :2; + ADD_CMD_drive :2; + Clock_out_drive :2; + DQ_termination :2; + DQS_termination :2; + ADD_CMD_input_pin_termination :2; + preset_odt_clk :2; + Power_down :1; + rank :1; + Command_Address_Pipe :2; + */ + { + switch (ddr_type) + { + default: + case DDR_OFF_MODE: + /* Below have already been set */ + /* CFG_DDR_SGMII_PHY->rpc95.rpc95 = 0x07; */ /* addcmd I/O*/ + /* CFG_DDR_SGMII_PHY->rpc96.rpc96 = 0x07; */ /* clk */ + /* CFG_DDR_SGMII_PHY->rpc97.rpc97 = 0x07; */ /* dq */ + /* CFG_DDR_SGMII_PHY->rpc98.rpc98 = 0x07; */ /* dqs */ + /* + * bits 15:14 connect to ibufmx DQ/DQS/DM + * bits 13:12 connect to ibufmx CA/CK + */ + CFG_DDR_SGMII_PHY->UNUSED_SPACE0[0] = 0x0U; + break; + case DDR3L: + case DDR3: + /* Required when rank x 2 */ + if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_RANK_MASK) ==\ + DDRPHY_MODE_TWO_RANKS) + { + CFG_DDR_SGMII_PHY->spio253.spio253 = 1U; + } + + { + /* + * firmware set this to 3'b100 for all cases except when we + * are in OFF mode (DDR3,DDR4,LPDDR3,LPDDR4). + */ + CFG_DDR_SGMII_PHY->rpc98.rpc98 = 0x04U; + } + /* + * SAR xxxx + * bits 15:14 connect to ibufmx DQ/DQS/DM + * bits 13:12 connect to ibufmx CA/CK + */ + CFG_DDR_SGMII_PHY->UNUSED_SPACE0[0] = 0x0U; + break; + case DDR4: + { + /* + * Sar 108017 + * ODT_STATIC setting is wrong for DDR4/LPDDR3, needs to + * be overwritten in embedded SW for E51 + * + * ODT_STATIC is set to 001 for DQ/DQS/DBI bits in + * DDR3/LPDDR4, this enables termination to VSS. + * + * This needs to be switched to VDDI termination. + * + * To do this, we do APB register writes to override + * the following PC bits: + * odt_static_dq=010 + * odt_static_dqs=010 + */ + CFG_DDR_SGMII_PHY->rpc10_ODT.rpc10_ODT = 2U; + CFG_DDR_SGMII_PHY->rpc11_ODT.rpc11_ODT = 2U; + /* + * SAR 108218 + * The firmware should set this to 3'b100 for + * all cases except when we are in OFF mode (DDR3,DDR4, + * LPDDR3,LPDDR4). + */ + CFG_DDR_SGMII_PHY->rpc98.rpc98 = 0x04U; + /* + * bits 15:14 connect to ibufmx DQ/DQS/DM + * bits 13:12 connect to ibufmx CA/CK + */ + CFG_DDR_SGMII_PHY->UNUSED_SPACE0[0] = 0x0U; + } + break; + case LPDDR3: + { + /* + * Sar 108017 + * ODT_STATIC setting is wrong for DDR4/LPDDR3, needs to be + * overwritten in embedded SW for E51 + * + * ODT_STATIC is set to 001 for DQ/DQS/DBI bits in + * DDR3/LPDDR4, this enables termination to VSS. + * + * This needs to be switched to VDDI termination. + * + * To do this, we should do APB register writes to override + * the following PC bits: + * odt_static_dq=010 + * odt_static_dqs=010 + */ + CFG_DDR_SGMII_PHY->rpc10_ODT.rpc10_ODT = 2U; + CFG_DDR_SGMII_PHY->rpc11_ODT.rpc11_ODT = 2U; + /* + * SAR 108218 + * I've reviewed the results, and the ibufmd bit should be + * fixed in firmware for ibufmd_dqs. Malachy please have + * the firmware set this to 3'b100 for all cases except + * when we are in OFF mode (DDR3,DDR4,LPDDR3,LPDDR4). + */ + CFG_DDR_SGMII_PHY->rpc98.rpc98 = 0x04U; + /* + * SAR xxxx + * bits 15:14 connect to ibufmx DQ/DQS/DM + * bits 13:12 connect to ibufmx CA/CK + */ + CFG_DDR_SGMII_PHY->UNUSED_SPACE0[0] = 0x0U; + } + break; + case LPDDR4: + { + /* + * We need to be able to implement different physical + * configurations of LPDDR4, given the twindie architecture. + * These are not fully decoded by the APB decoder (we dont + * have all the options). + * Basically we want to support: + * Hook the CA buses from the 2 die up in parallel on the + * same FPGA pins + * Hook the CA buses from the 2 die up in parallel using + * the mirrored FPGA pins (IE CA_A/CA_B) + * Some combination of the 2, ie duplicate the clocks but + * not the CA, duplicate the clocks and command, but not + * address, etc. + */ + /* OVRT_EN_ADDCMD1 (default 0xF00), register named ovrt11 */ +#ifndef LIBERO_SETTING_RPC_EN_ADDCMD0_OVRT9 + /* + * If this define is not present, indicates older + * Libero core (pre 2.0.109) + * So we run this code + */ + CFG_DDR_SGMII_PHY->ovrt10.ovrt10 =\ + LIBERO_SETTING_RPC_EN_ADDCMD1_OVRT10; + { + /* Use pull-ups to set the CMD/ADD ODT */ + CFG_DDR_SGMII_PHY->rpc245.rpc245 =\ + 0x00000000U; + + CFG_DDR_SGMII_PHY->rpc237.rpc237 =\ + 0xffffffff; + } + + /* OVRT_EN_ADDCMD2 (default 0xE06U), register named ovrt12 */ + CFG_DDR_SGMII_PHY->ovrt11.ovrt11 =\ + LIBERO_SETTING_RPC_EN_ADDCMD2_OVRT11; +#endif + /* Required when rank x 2 */ + if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_RANK_MASK) ==\ + DDRPHY_MODE_TWO_RANKS) + { + /* todo: need to verify this setting with verification */ + CFG_DDR_SGMII_PHY->spio253.spio253 = 1; + } + + { + /* + * SAR 108218 + * I've reviewed the results, and the ibufmd bit should be + * fixed in firmware for ibufmd_dqs. Malachy please have the + * firmware set this to 3'b100 for all cases except when we + * are in OFF mode (DDR3,DDR4,LPDDR3,LPDDR4). + */ + CFG_DDR_SGMII_PHY->rpc98.rpc98 = 0x04U; + } + /* + * SAR xxxx + * bits 15:14 connect to ibufmx DQ/DQS/DM + * bits 13:12 connect to ibufmx CA/CK + */ + CFG_DDR_SGMII_PHY->UNUSED_SPACE0[0] = 0xA000U; + + } + + break; + } + } + + { + + /* + * sar107009 found by Paul in Crevin, + * This has been fixed in tag g5_mss_ddrphy_apb tag 2.9.130 + * todo: remove this software workaround as no longer required + * + * Default of rpc27 should be 2, currently is 0 + * We will set to 2 for the moment with software. + */ + CFG_DDR_SGMII_PHY->rpc27.rpc27 = 0x2U; + /* + * Default of rpc27 Issue see by Paul/Alister 10th June + * tb_top.duv_wrapper.u_design.mss_custom.gbank6.tip.gapb.\ + * MAIN.u_apb_mss_decoder_io.rpc203_spare_iog_dqsn + */ + CFG_DDR_SGMII_PHY->rpc203.rpc203 = 0U; + } + + { + /* + * + * We'll have to pass that one in via E51, meaning APB writes to + * addresses: + * 0x2000 7384 rpc1_ODT ODT_CA + * 0x2000 7388 rpc2_ODT RPC_ODT_CLK + * 0x2000 738C rpc3_ODT ODT_DQ + * 0x2000 7390 rpc4_ODT ODT_DQS + * + * todo: replace with Libero settings below, once values verified + */ + CFG_DDR_SGMII_PHY->rpc1_ODT.rpc1_ODT = LIBERO_SETTING_RPC_ODT_ADDCMD; + CFG_DDR_SGMII_PHY->rpc2_ODT.rpc2_ODT = LIBERO_SETTING_RPC_ODT_CLK; + CFG_DDR_SGMII_PHY->rpc3_ODT.rpc3_ODT = LIBERO_SETTING_RPC_ODT_DQ; + CFG_DDR_SGMII_PHY->rpc4_ODT.rpc4_ODT = LIBERO_SETTING_RPC_ODT_DQS; + } + { + /* + * bclk_sel_clkn - selects bclk sclk training clock + */ + CFG_DDR_SGMII_PHY->rpc19.rpc19 = 0x01U; /* bclk_sel_clkn */ + /* + * add cmd - selects bclk sclk training clock + */ + CFG_DDR_SGMII_PHY->rpc20.rpc20 = 0x00U; /* bclk_sel_clkp */ + + } + + { + /* + * Each lane has its own FIFO. This paramater adjusts offset for all lanes. + */ +#if (TUNE_RPC_166_VALUE == 1) + CFG_DDR_SGMII_PHY->rpc166.rpc166 = rpc_166_fifo_offset; +#endif + } + + /* + * Override RPC bits for weak PU and PD's + * Set over-ride bit for unused I/O + */ + config_ddr_io_pull_up_downs_rpc_bits(ddr_type); +} + +/** + Info on OFF modes: + + OFF MODE from reset- I/O not being used + MSSIO from reset- non default values + Needs non default values to completely go completely OFF + Drive bits and ibuff mode + Ciaran to define what need to be done + SAR107676 + DDR - by default put to DDR4 mode so needs active intervention + Bills sac spec (DDR PHY SAC spec section 6.1) + Mode register set to 7 + Ibuff mode set to 7 (rx turned off) + P-Code/ N-code of no relevance as not used + Disable DDR PLL + Will be off from reset- no need + Need to reflash + DDR APB ( three resets - soft reset bit 0 to 1) + Drive odt etc + SGMII - from reset nothing to be done + See Jeff's spread sheet- default values listed + Extn clock off also defined in spread sheet + */ + + +/** + * ddr_off_mode(void) + * Assumed in Dynamic mode. + * i.e. + * SCB dynamic enable bit is high + * MSS core_up = 1 + * dce[0,1,2] 0,0,0 + * flash valid = 1 + * IP: + * DECODER_DRIVER, ODT, IO all out of reset + * + * DDR PHY off mode that I took from version 1.58 of the DDR SAC spec. + * 1. DDR PHY OFF mode (not used at all). + * 1. Set the DDR_MODE register to 7 + * This will disable all the drive and ODT to 0, as well as set all WPU bits. + * 2. Set the RPC_IBUF_MD_* registers to 7 + * This will disable all receivers. + * 3. Set the REG_POWERDOWN_B register to 0 + * This will disable the DDR PLL + * + */ +static void ddr_off_mode(void) +{ + /* + * DDR PLL is not turn on on reset- so no need to do anything + */ + /* + * set the mode register to 7 => off mode + * From the DDRPHY training firmware spec.: + * If the DDR interface is unused, the firmware will have to write 3'b111 + * into the APB_DDR_MODE register. This will disable all the DRIVERs, ODT + * and INPUT receivers. + * By default, WPD will be applied to all pads. + * + * If a user wants to apply WPU, this will have to be applied through + * firmware, by changing all RPC_WPU_*=0, and RPC_WPD_*=1, via APB register + * writes. + * + * Unused IO within an interface will automatically be shut off, as unused + * DQ/DM/DQS/and CA buffers and odt are automatically disabled by the + * decode, and put into WPD mode. + * Again, if the user wants to change this to WPU, the will have to write + * RPC_WPU_*=0 and RPC_WPD_*=1 to override the default. + * + */ + /* Note: DMI_DBI [8:1] needs to be 0 (off) during training */ + CFG_DDR_SGMII_PHY->DDRPHY_MODE.DDRPHY_MODE =\ + (LIBERO_SETTING_DDRPHY_MODE_OFF /* & DMI_DBI_MASK */); + /* + * VS for off mode + */ + CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS =\ + LIBERO_SETTING_DPC_BITS_OFF_MODE; + + /* + * Toggle decoder here + * bit 0 == PERIPH soft reset, auto cleared + */ + CFG_DDR_SGMII_PHY->SOFT_RESET_DECODER_DRIVER.SOFT_RESET_DECODER_DRIVER= 1U; + CFG_DDR_SGMII_PHY->SOFT_RESET_DECODER_ODT.SOFT_RESET_DECODER_ODT = 1U; + CFG_DDR_SGMII_PHY->SOFT_RESET_DECODER_IO.SOFT_RESET_DECODER_IO = 1U; + + /* + * set ibuff mode to 7 in off mode + * + */ + CFG_DDR_SGMII_PHY->rpc95.rpc95 = 0x07; /* addcmd I/O*/ + CFG_DDR_SGMII_PHY->rpc96.rpc96 = 0x07; /* clk */ + CFG_DDR_SGMII_PHY->rpc97.rpc97 = 0x07; /* dq */ + CFG_DDR_SGMII_PHY->rpc98.rpc98 = 0x07; /* dqs */ + + /* + * Default WPU, modify If user wants Weak Pull Up + */ + /* + * UNUSED_SPACE0 + * bits 15:14 connect to ibufmx DQ/DQS/DM + * bits 13:12 connect to ibufmx CA/CK + * todo: Do we need to add Pu/PD option for off mode to Libero setting? + */ + CFG_DDR_SGMII_PHY->UNUSED_SPACE0[0] = 0x0000U; + + /* + * REG_POWERDOWN_B on PLL turn-off, in case was turned on. + */ + ddr_pll_config_scb_turn_off(); + return; +} + + +/***************************************************************************//** + * Number of tests which write and read from DDR + * Tests data path through the cache and through AXI4 switch. + */ +#ifdef DDR_SANITY_CHECKS_EN +static uint8_t memory_tests(void) +{ + uint64_t shift_walking_one = 4U; + uint64_t start_address = 0x0000000000000000U; + uint8_t error = 0U; + SIM_FEEDBACK1(199U); + /* + * Verify seg1 reg 2, datapath through AXI4 switch + */ + while(shift_walking_one <= 28U) /* 28 => 1G, as 2**28 == 256K and this is + mult by (4 lanes) */ + { + SIM_FEEDBACK1(shift_walking_one); + start_address = (uint64_t)(0xC0000000U + (0x1U<<shift_walking_one)); + error = rw_sanity_chk((uint64_t *)start_address , (uint32_t)0x5U); + + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(200U); + } + shift_walking_one++; + } + SIM_FEEDBACK1(500U); + /* + * Verify seg1 reg 3, datapath through AXI4 switch + */ + shift_walking_one = 4U; + while(shift_walking_one <= 28U) //28 => 1G + { + SIM_FEEDBACK1(shift_walking_one); + start_address = (uint64_t)(0x1400000000U + (0x1U<<shift_walking_one)); + error = rw_sanity_chk((uint64_t *)start_address , (uint32_t)0x5U); + + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(208U); + } + + /* check upper bound */ + if(shift_walking_one >= 4U) + { + start_address = (uint64_t)(0x1400000000U + \ + (((0x1U<<(shift_walking_one +1)) - 1U) -0x0F) ); + error = rw_sanity_chk((uint64_t *)start_address , (uint32_t)0x5U); + + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(201U); + } + } + + shift_walking_one++; + } + /* + * Verify mtc + */ + SIM_FEEDBACK1(600U); + shift_walking_one = 4U; + while(shift_walking_one <= 28U) //28 => 1G + { + SIM_FEEDBACK1(shift_walking_one); + start_address = (uint64_t)(0x1U<<shift_walking_one); + error = mtc_sanity_check(start_address); + + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(203U); + } + + /* check upper bound */ + if(shift_walking_one >= 4U) + { + start_address = (uint64_t)((((0x1U<<(shift_walking_one +1)) - 1U)\ + -0x0F) ); + error = mtc_sanity_check(start_address); + + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(204U); + } + } + shift_walking_one++; + } + + /* + * Verify seg0 reg 0, datapath through cache + */ + SIM_FEEDBACK1(700U); + shift_walking_one = 4U; + while(shift_walking_one <= 27U) //28 => 1G + { + SIM_FEEDBACK1(shift_walking_one); + start_address = (uint64_t)(0x80000000U + (0x1U<<shift_walking_one)); + error = rw_sanity_chk((uint64_t *)start_address , (uint32_t)0x5U); + + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(206U); + } + shift_walking_one++; + } + + /* + * Verify seg0 reg 1, datapath through cache, + */ +#if 0 /* issue with cache setup for 64 address width, need to checkout */ + SIM_FEEDBACK1(800U); + shift_walking_one = 4U; + while(shift_walking_one <= 28U) //28 => 1G (0x10000000(address) * 4 (32bits wide)) + { + SIM_FEEDBACK1(shift_walking_one); + start_address = (uint64_t)(0x1000000000U + (0x1U<<shift_walking_one)); + error = rw_sanity_chk((uint64_t *)start_address , (uint32_t)0x5U); + + if(error) + { + ddr_error_count++; + SIM_FEEDBACK1(207U); + } + +#if 0 /* this check will not work as written, need to look further into flushing + cache as part of this test */ + /* + * read back via axi switch datapath to make sure write through on + * cache occurred + */ + start_address = (uint64_t)(0x1400000000U + (0x1U<<shift_walking_one)); + error = read_back_sanity_check((uint64_t *)start_address , 0x5UL); + + if(error) + ddr_error_count++; + + shift_walking_one++; +#endif + } +#endif + + SIM_FEEDBACK1(299U); + return (error); +} +#endif + +/***************************************************************************//** + * rw_sanity_chk() + * writes and verifies reads back from DDR + * Uses values defined in the test_string[] + * @param address + * @param count + * @return non zero if error + */ +#ifdef DDR_SANITY_CHECKS_EN +static uint8_t rw_sanity_chk(uint64_t * address, uint32_t count) +{ + volatile uint64_t *DDR_word_ptr; + uint64_t value; + uint8_t error = 0U; + /* DDR memory address from E51 - 0xC0000000 is non cache access */ + DDR_word_ptr = address; + + volatile uint32_t i = 0x0U; + + /* + * First fill + */ + while(i < count) + { + *DDR_word_ptr = test_string[i & 0xfU]; + + value = *DDR_word_ptr; + + if( value != test_string[i & 0xfU]) + { + value = *DDR_word_ptr; + if( value != test_string[i & 0xfU]) + { + ddr_error_count++; + error = 1; + } + } + ++i; + DDR_word_ptr = DDR_word_ptr + 1U; + } + /* + * Recheck read, if first read successful + */ + if(error == 0) + { + /* DDR memory address from E51 - 0xC0000000 is non cache access */ + DDR_word_ptr = address; + i = 0x0U; + while(i < count) + { + if( *DDR_word_ptr != test_string[i & 0xfU]) + { + ddr_error_count++; + error = 1; + } + ++i; + DDR_word_ptr = DDR_word_ptr + 1U; + } + } + return error; +} +#endif + +/***************************************************************************//** + * + * @param address + * @param count + * @return + */ +#if 0 /* todo: review, add in if required */ +static uint8_t read_back_sanity_check(uint64_t * address, uint32_t count) +{ + volatile uint64_t *DDR_word_ptr; + uint8_t error = 0U; + DDR_word_ptr = address; /* DDR memory address from E51 - 0xC0000000 is + non cache access */ + + volatile uint32_t i = 0x0U; + + /* + * Recheck read, if first read successful + */ + if(error == 0) + { + DDR_word_ptr = address; /* DDR memory address from E51 - 0xC0000000 + is non cache access */ + i = 0x0U; + while(i < count) + { + if( *DDR_word_ptr != test_string[i & 0xfU]) + { + ddr_error_count++; + error = 1; + } + ++i; + DDR_word_ptr = DDR_word_ptr + 1U; + } + } + return error; +} +#endif + +/***************************************************************************//** + * Memory test Core sanity check + * @param start_address + * @return non zero if error + */ +#ifdef DDR_SANITY_CHECKS_EN +static uint8_t mtc_sanity_check(uint64_t start_address) +{ + uint8_t result; + uint64_t size = 4U; + result = MTC_test((0xFU), start_address, size ); + return result; +} +#endif + + +/***************************************************************************//** + * + * load_dq(lane) + * set dyn_ovr_dlycnt_dq_load* = 0 + * set expert_dfi_status_override_to_shim = 0x7 + * set expert_mode_en = 0x21 + * set dyn_ovr_dlycnt_dq_load* = 1 + * set dyn_ovr_dlycnt_dq_load* = 0 + * set expert_mode_en = 0x8 + * + * @param lane + */ +static void load_dq(uint8_t lane) +{ + //set dyn_ovr_dlycnt_dq_load* = 0 + if(lane < 4U) + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg0.expert_dlycnt_move_reg0 = 0U; + } + else + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg1.expert_dlycnt_move_reg1 = \ + (CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg1.expert_dlycnt_move_reg1\ + & (uint32_t)~0x0FU); + } + //set expert_dfi_status_override_to_shim = 0x7 + CFG_DDR_SGMII_PHY->expert_dfi_status_override_to_shim.expert_dfi_status_override_to_shim = 0x07U; + //set expert_mode_en = 0x21 + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x21U; + //set dyn_ovr_dlycnt_dq_load* = 1 + if(lane < 4U) + { + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg0.expert_dlycnt_load_reg0 =\ + (0xFFU << (lane * 8U)); + } + else + { + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1 |=\ + 0x0FU; + } + //set dyn_ovr_dlycnt_dq_load* = 0 + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg0.expert_dlycnt_load_reg0 = 0U; + if(lane < 4U) + { + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg0.expert_dlycnt_load_reg0 = 0U; + } + else + { + CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1 = \ + (CFG_DDR_SGMII_PHY->expert_dlycnt_load_reg1.expert_dlycnt_load_reg1\ + & (uint32_t)~0x0FU); + } + //set expert_mode_en = 0x8 + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x8U; +} + +/***************************************************************************//** + * increment_dq() + * set dyn_ovr_dlycnt_dq_move* = 0 + * set dyn_ovr_dlycnt_dq_direction* = 1 + * set expert_dfi_status_override_to_shim = 0x7 + * set expert_mode_en = 0x21 + * + * #to increment multiple times loop the move=0/1 multiple times + * set dyn_ovr_dlycnt_dq_move* = 1 + * set dyn_ovr_dlycnt_dq_move* = 0 + * # + * set expert_mode_en = 0x8 + * @param lane + * @param move_count + */ +#ifdef SW_CONFIG_LPDDR_WR_CALIB_FN +static void increment_dq(uint8_t lane, uint32_t move_count) +{ + //set dyn_ovr_dlycnt_dq_move* = 0 + if(lane < 4U) + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg0.expert_dlycnt_move_reg0 = 0U; + } + else + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg1.expert_dlycnt_move_reg1 = \ + (CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg1.expert_dlycnt_move_reg1\ + & ~0x0FU); + } + //set dyn_ovr_dlycnt_dq_direction* = 1 + if(lane < 4U) + { + CFG_DDR_SGMII_PHY->expert_dlycnt_direction_reg0.expert_dlycnt_direction_reg0\ + = (0xFFU << (lane * 8U)); + } + else + { + /* only four lines, use 0xFU */ + CFG_DDR_SGMII_PHY->expert_dlycnt_direction_reg1.expert_dlycnt_direction_reg1 |= 0xFU; + } + /* set expert_dfi_status_override_to_shim = 0x7 */ + CFG_DDR_SGMII_PHY->expert_dfi_status_override_to_shim.expert_dfi_status_override_to_shim = 0x07U; + /* set expert_mode_en = 0x21 */ + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x21U; + /* #to increment multiple times loop the move=0/1 multiple times */ + move_count = move_count + move_count + move_count; + while(move_count) + { + // set dyn_ovr_dlycnt_dq_move* = 1 + if(lane < 4U) + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg0.expert_dlycnt_move_reg0\ + = (0xFFU << (lane * 8U)); + } + else + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg1.expert_dlycnt_move_reg1\ + |= 0x0FU; + } + // set dyn_ovr_dlycnt_dq_move* = 0 + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg0.expert_dlycnt_move_reg0 = 0U; + if(lane < 4U) + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg0.expert_dlycnt_move_reg0\ + = 0U; + } + else + { + CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg1.expert_dlycnt_move_reg1 = \ + (CFG_DDR_SGMII_PHY->expert_dlycnt_move_reg1.expert_dlycnt_move_reg1 & ~0x0FU); + } + move_count--; + } + /* set expert_mode_en = 0x8 */ + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x8U; +} +#endif + +/***************************************************************************//** + * + */ +static void set_write_calib(uint8_t user_lanes) +{ + uint32_t temp = 0U; + uint8_t lane_to_set; + uint8_t shift = 0U; + + /* + * Calculate the calibrated value and write back + */ + calib_data.write_cal.lane_calib_result = 0U; + for (lane_to_set = 0x00U;\ + lane_to_set<user_lanes /*USER_TOTAL_LANES_USED */; lane_to_set++) + { + temp = calib_data.write_cal.lower[lane_to_set]; + calib_data.write_cal.lane_calib_result = \ + calib_data.write_cal.lane_calib_result | (temp << (shift)); + shift = (uint8_t)(shift + 0x04U); + } + + /* + * bit 3 must be set if we want to use the + * expert_wrcalib + * register + */ + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x00000008U; + + SIM_FEEDBACK1(0xFF000000); + SIM_FEEDBACK1(calib_data.write_cal.lane_calib_result); + SIM_FEEDBACK1(0xFF000000); + + /* set the calibrated value */ + CFG_DDR_SGMII_PHY->expert_wrcalib.expert_wrcalib =\ + calib_data.write_cal.lane_calib_result; +} + +/***************************************************************************//** + * + * @param lane_to_set + */ +#ifdef SW_CONFIG_LPDDR_WR_CALIB_FN +static void set_calc_dq_delay_offset(uint8_t lane_to_set) +{ + uint32_t move_count; + + load_dq(lane_to_set); /* set to start */ + + /* shift by 1 to divide by two */ + move_count = ((calib_data.dq_cal.upper[lane_to_set] -\ + calib_data.dq_cal.lower[lane_to_set] ) >> 1U) +\ + calib_data.dq_cal.lower[lane_to_set]; + + increment_dq(lane_to_set, move_count); + +} +#endif + +/***************************************************************************//** + * + * @param user_lanes + */ +#ifdef SW_CONFIG_LPDDR_WR_CALIB_FN +static void set_calib_values(uint8_t user_lanes) +{ + uint8_t lane_to_set; + uint32_t move_count; + + for (lane_to_set = 0x00U;\ + lane_to_set< user_lanes ; lane_to_set++) + { + set_calc_dq_delay_offset(lane_to_set); + } + + /* and set the write calibration calculated */ + set_write_calib(user_lanes); +} +#endif + + +/***************************************************************************//** + * write_calibration_using_mtc + * Use Memory Test Core plugged in to the front end of the DDR controller to + * perform lane-based writes and read backs and increment write calibration + * offset for each lane until data match occurs. The Memory Test Core is the + * basis for all training. + * + * @param number_of_lanes_to_calibrate + * @return + */ +static uint8_t \ + write_calibration_using_mtc(uint8_t number_of_lanes_to_calibrate) +{ + uint8_t laneToTest; + uint32_t result = 0U; + uint32_t cal_data; + uint64_t start_address = 0x0000000000000000ULL; + uint32_t size = ONE_MB_MTC; /* Number of reads for each iteration 2**size*/ + + calib_data.write_cal.status_lower = 0U; + /* + * bit 3 must be set if we want to use the + * expert_wrcalib + * register + */ + CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x00000008U; + + /* + * training carried out here- sweeping write calibration offset from 0 to F + * Explanation: A register, expert_wrcalib, is described in MSS DDR TIP + * Register Map [1], and its purpose is to delay--by X number of memory clock + * cycles--the write data, write data mask, and write output enable with the + * respect to the address and command for each lane. + */ + for (cal_data=0x00000U;cal_data<0xfffffU;cal_data=cal_data+0x11111U) + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\rCalibration offset used:",cal_data &0xFUL); +#endif + CFG_DDR_SGMII_PHY->expert_wrcalib.expert_wrcalib = cal_data; + + for (laneToTest = 0x00U; laneToTest<number_of_lanes_to_calibrate;\ + laneToTest++) + { + /* + * read once to flush MTC. During write calibration the first MTC read + * must be discarded as it is unreliable after a series of bad writes. + */ + uint8_t mask = (uint8_t)(1U<<laneToTest); + result = MTC_test(mask, start_address, size, MTC_COUNTING_PATTERN, MTC_ADD_SEQUENTIAL, &result); + /* Read using different patterns */ + result |= MTC_test(mask, start_address, size, MTC_COUNTING_PATTERN, MTC_ADD_SEQUENTIAL, &result); + result |= MTC_test(mask, start_address, size, MTC_WALKING_ONE, MTC_ADD_SEQUENTIAL, &result); + result |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM, MTC_ADD_SEQUENTIAL, &result); + result |= MTC_test(mask, start_address, size, MTC_NO_REPEATING_PSEUDO_RANDOM, MTC_ADD_SEQUENTIAL, &result); + result |= MTC_test(mask, start_address, size, MTC_ALT_ONES_ZEROS, MTC_ADD_SEQUENTIAL, &result); + result |= MTC_test(mask, start_address, size, MTC_ALT_5_A, MTC_ADD_SEQUENTIAL, &result); + result |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM_16BIT, MTC_ADD_SEQUENTIAL, &result); + result |= MTC_test(mask, start_address, size, MTC_PSEUDO_RANDOM_8BIT, MTC_ADD_SEQUENTIAL, &result); + + if(result == 0U) /* if passed for this lane */ + { + if((calib_data.write_cal.status_lower & (0x01U<<laneToTest)) \ + == 0U) /* Still looking for good value */ + { + calib_data.write_cal.lower[laneToTest] = (cal_data & 0xFU); + calib_data.write_cal.status_lower |= (0x01U<<laneToTest); + } + /* + * Check the result + */ +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\rLane passed:",laneToTest); + (void)uprint32(g_debug_uart, " All lanes status:",calib_data.write_cal.status_lower); +#endif + uint32_t laneToCheck; + for (laneToCheck = 0x00U;\ + laneToCheck<number_of_lanes_to_calibrate; laneToCheck++) + { + if(((calib_data.write_cal.status_lower) &\ + (0x01U<<laneToCheck)) == 0U) + { + result = 1U; /* not finished, still looking */ + break; + } + } + if(result == 0U) /* if true, we are good for all lanes, can stop + looking */ + { + SIM_FEEDBACK1(0xF7000000); + break; + } + } + else + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\rLane failed:",laneToTest); + (void)uprint32(g_debug_uart, " All lanes status:",calib_data.write_cal.status_lower); +#endif + } + + } /* end laneToTest */ + if(result == 0U) /* if true, we are good for all lanes, can stop */ + { /* looking */ + SIM_FEEDBACK1(0xF8000000); + break; + } + } /* end cal_data */ + + SIM_FEEDBACK1(0x01000000); + SIM_FEEDBACK1(calib_data.write_cal.lower[0]); + SIM_FEEDBACK1(0x02000000); + SIM_FEEDBACK1(calib_data.write_cal.lower[1]); + SIM_FEEDBACK1(0x03000000); + SIM_FEEDBACK1(calib_data.write_cal.lower[2]); + SIM_FEEDBACK1(0x04000000); + SIM_FEEDBACK1(calib_data.write_cal.lower[3]); + SIM_FEEDBACK1(0x05000000); + SIM_FEEDBACK1(calib_data.write_cal.lower[4]); + SIM_FEEDBACK1(0x06000000); + SIM_FEEDBACK1(calib_data.write_cal.lower[5]); + SIM_FEEDBACK1(0x07000000); + + /* if calibration successful, calculate and set the value */ + if(result == 0U) + { + /* and set the write calibration which has been calculated */ + set_write_calib(number_of_lanes_to_calibrate); + } + + SIM_FEEDBACK1(0x08000000); + SIM_FEEDBACK1(result); + SIM_FEEDBACK1(0x08000000); + return result; +} + + +/** + * MODE register write + * @param MR_ADDR + * @param MR_DATA + * @return fail/pass + */ +#ifdef SET_VREF_LPDDR4_MODE_REGS +static uint8_t mode_register_write(uint32_t MR_ADDR, uint32_t MR_DATA) +{ + uint32_t test = 0xFFFFU; + uint32_t result = 0U; + /* + * + */ + //DDRCFG->MC_BASE2.INIT_MRR_MODE.INIT_MRR_MODE = 0x01; + DDRCFG->MC_BASE2.INIT_MR_ADDR.INIT_MR_ADDR = MR_ADDR ; + /* + * next: + * write desired VREF calibration range (0=Range 1, 1=Range 2) to bit 6 + * of MR6 + * write 0x00 to bits 5:0 of MR6 (base calibration value) + */ + DDRCFG->MC_BASE2.INIT_MR_WR_DATA.INIT_MR_WR_DATA = MR_DATA; + DDRCFG->MC_BASE2.INIT_MR_WR_MASK.INIT_MR_WR_MASK = 0U; + + DDRCFG->MC_BASE2.INIT_MR_W_REQ.INIT_MR_W_REQ = 0x01U; + while((DDRCFG->MC_BASE2.INIT_ACK.INIT_ACK & 0x01U) == 0U) /* wait for ack- + to confirm register is written */ + { + test--; + if(test-- == 0U) + { + result = 1U; + break; + } + } + return result; +} +#endif + +#define VREF_INVALID 0x01U +/***************************************************************************//** + * FPGA_VREFDQ_calibration_using_mtc(void) + * vary DQ voltage and set optimum DQ voltage + * @return + */ +#ifdef VREFDQ_CALIB + /* + * This step is optional + * todo: Test once initial board verification complete + */ +static uint8_t FPGA_VREFDQ_calibration_using_mtc(void) +{ + uint8_t laneToTest, result = 0U; + uint64_t mask; + uint32_t vRef; + uint64_t start_address = 0x0000000000000000ULL; + uint64_t size = 4U; + + /* + * Step 2a. FPGA VREF (Local VREF training) + * Train FPGA VREF using the vrgen_h and vrgen_v registers + */ + { + /* + * To manipulate the FPGA VREF value, firmware must write to the + * DPC_BITS register, located at physical address 0x2000 7184. + * Full documentation for this register can be found in + * DFICFG Register Map [4]. + */ + /* + * See DPC_BITS definition in .h file + */ + /* CFG_DDR_SGMII_PHY->DPC_BITS.bitfield.dpc_vrgen_h; */ + /* CFG_DDR_SGMII_PHY->DPC_BITS.bitfield.dpc_vrgen_v; */ + + } + + /* + * training carried out here- sweeping write calibration offset from 0 to F + * Explanation: A register, expert_wrcalib, is described in MSS DDR TIP + * Register Map [1], and its purpose is to delay--by X number of memory + * clock cycles--the write data, write data mask, and write output enable + * with the respect to the address and command for each lane. + */ + calib_data.fpga_vref.vref_result = 0U; + calib_data.fpga_vref.lower = VREF_INVALID; + calib_data.fpga_vref.upper = VREF_INVALID; + calib_data.fpga_vref.status_lower = 0x00U; + calib_data.fpga_vref.status_upper = 0x00U; + mask = 0xFU; /* todo: obtain data width from user parameters */ + uint32_t count = 0U; + /* each bit .25% of VDD ?? */ + for (vRef=(0x1U<<4U);vRef<(0x1fU<<4U);vRef=vRef+(0x1U<<4U)) + { + /* + CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS =\ + (CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS & (~(0x1U<<10U))); + CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS =\ + (CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS & (~(0x1fU<<4U))) | vRef; + */ + /* need to set via the SCB, otherwise reset required. So lines below + * rather than above used */ + + IOSCB_BANKCONT_DDR->dpc_bits = (IOSCB_BANKCONT_DDR->dpc_bits &\ + (~(0x1U<<10U))); + IOSCB_BANKCONT_DDR->dpc_bits = (IOSCB_BANKCONT_DDR->dpc_bits &\ + (~(0x1fU<<4U))) | vRef; + + + /* read one to flush MTC - this is required */ + result = MTC_test(1U<<laneToTest, start_address, size); + /* Read twice, two different patterns will be used */ + result = MTC_test(1U<<laneToTest, start_address, size); + result |= MTC_test(1U<<laneToTest, start_address, size); + if((result == 0U)&&(calib_data.fpga_vref.lower == VREF_INVALID)) + { + calib_data.fpga_vref.lower = vRef; + calib_data.fpga_vref.upper = vRef; + calib_data.fpga_vref.status_lower = 0x01; + } + else if((result == 0U)&&(calib_data.fpga_vref.lower != VREF_INVALID)) + { + calib_data.fpga_vref.upper = vRef; + calib_data.fpga_vref.status_upper = 0x01; + } + else if(calib_data.fpga_vref.upper != VREF_INVALID) + { + break; /* we are finished */ + } + else + { + /* nothing to do */ + } + } + + if(calib_data.fpga_vref.upper != VREF_INVALID) /* we found lower/upper */ + { + /* + * now set vref + * calculate optimal VREF calibration value = + * (left side + right side) / 2 + * */ + vRef = ((calib_data.fpga_vref.lower + calib_data.fpga_vref.upper)>>1U); + CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS =\ + (CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS & (0x1fU<<4U)) | vRef; + /* need to set via the SCB, otherwise reset required. */ + IOSCB_BANKCONT_DDR->dpc_bits = (IOSCB_BANKCONT_DDR->dpc_bits &\ + (0x1fU<<4U)) | vRef; + } + else + { + result = 1U; /* failed to get good data at any voltage level */ + } + + return result; +} + +#endif + +#ifdef VREFDQ_CALIB + /* + * This step is optional + * todo: Test once initial board verification complete + */ +#define MEM_VREF_INVALID 0xFFFFFFFFU +/***************************************************************************//** + * + * VREFDQ_calibration_using_mtc + * In order to write to mode registers, the E51 must use the INIT_* interface + * at the front end of the DDR controller, + * which is available via a series of control registers described in the DDR + * CSR APB Register Map. + * + * @return + */ +static uint8_t VREFDQ_calibration_using_mtc(void) +{ + uint8_t laneToTest, result = 0U; + uint64_t mask; + uint32_t vRef; + uint64_t start_address = 0x00000000C0000000ULL; + uint64_t size = 4U; + + /* + * Step 2a. FPGA VREF (Local VREF training) + * Train FPGA VREF using the vrgen_h and vrgen_v registers + */ + { + /* + * + */ + DDRCFG->MC_BASE2.INIT_MRR_MODE.INIT_MRR_MODE = 0x01U; + DDRCFG->MC_BASE2.INIT_MR_ADDR.INIT_MR_ADDR = 6U ; + /* + * next: + * write desired VREF calibration range (0=Range 1, 1=Range 2) to bit 6 + * of MR6 + * write 0x00 to bits 5:0 of MR6 (base calibration value) + */ + DDRCFG->MC_BASE2.INIT_MR_WR_DATA.INIT_MR_WR_DATA = 0U; + DDRCFG->MC_BASE2.INIT_MR_WR_MASK.INIT_MR_WR_MASK = (0x01U <<6U) |\ + (0x3FU) ; + + DDRCFG->MC_BASE2.INIT_MR_W_REQ.INIT_MR_W_REQ = 0x01U; + if((DDRCFG->MC_BASE2.INIT_ACK.INIT_ACK & 0x01U) == 0U) /* wait for ack- + to confirm register is written */ + { + + } + } + + /* + * training carried out here- sweeping write calibration offset from 0 to F + * Explanation: A register, expert_wrcalib, is described in MSS DDR TIP + * Register Map [1], and its purpose is to delay--by X number of memory clock + * cycles--the write data, write data mask, and write output enable with the + * respect to the address and command for each lane. + */ + calib_data.mem_vref.vref_result = 0U; + calib_data.mem_vref.lower = MEM_VREF_INVALID; + calib_data.mem_vref.upper = MEM_VREF_INVALID; + calib_data.mem_vref.status_lower = 0x00U; + calib_data.mem_vref.status_upper = 0x00U; + mask = 0xFU; /* todo: obtain data width from user paramaters */ + + for (vRef=(0x1U<<4U);vRef<0x3fU;vRef=(vRef+0x1U)) + { + /* + * We change the value in the RPC register, but we will lso need to + * change SCB as will not be reflected without a soft reset + */ + CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS =\ + (CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS & (0x1fU<<4U)) | vRef; + /* need to set via the SCB, otherwise reset required. */ + IOSCB_BANKCONT_DDR->dpc_bits = (IOSCB_BANKCONT_DDR->dpc_bits\ + & (0x1fU<<4U)) | vRef; + + /* read one to flush MTC - this is required */ + result = MTC_test(1U<<laneToTest, start_address, size); + /* Read twice, two different patterns will be used */ + result = MTC_test(1U<<laneToTest, start_address, size); + result |= MTC_test(1U<<laneToTest, start_address, size); + if((result == 0U)&&(calib_data.mem_vref.lower == MEM_VREF_INVALID)) + { + calib_data.mem_vref.lower = vRef; + calib_data.mem_vref.upper = vRef; + calib_data.mem_vref.status_lower = 0x01; + } + else if((result == 0U)&&(calib_data.mem_vref.lower != MEM_VREF_INVALID)) + { + calib_data.mem_vref.upper = vRef; + calib_data.mem_vref.status_lower = 0x01; + } + else if(calib_data.mem_vref.upper != MEM_VREF_INVALID) + { + break; /* we are finished */ + } + else + { + /* continue */ + } + + } + + if(calib_data.mem_vref.upper != MEM_VREF_INVALID) /* we found lower/upper */ + { + /* + * now set vref + * calculate optimal VREF calibration value = + * (left side + right side) / 2 + * */ + vRef = ((calib_data.mem_vref.lower + calib_data.mem_vref.lower)>1U); + CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS =\ + (CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS & (0x1fU<<4U)) | vRef; + /* need to set via the SCB, otherwise reset required. */ + IOSCB_BANKCONT_DDR->dpc_bits = (IOSCB_BANKCONT_DDR->dpc_bits & (0x1fU<<4U)) | vRef; + } + else + { + result = 1U; /* failed to get good data at any voltage level */ + } + + return result; + } +#endif + +/***************************************************************************//** + * MTC_test + * test memory using the NWL memory test core + * There are numerous options + * todo: Add user input as to option to use? + * @param laneToTest + * @param mask0 + * @param mask1 some lane less DQ as only used for parity + * @param start_address + * @param size = x, where x is used as power of two 2**x e.g. 256K => x == 18 + * @return pass/fail + */ +static uint8_t MTC_test(uint8_t mask, uint64_t start_address, uint32_t size, MTC_PATTERN data_pattern, MTC_ADD_PATTERN add_pattern, uint32_t *error) +{ + if((*error & MTC_TIMEOUT_ERROR) == MTC_TIMEOUT_ERROR) + { + return (uint8_t)*error; + } + /* Write Calibration - first configure memory test */ + { + /* + * write calibration + * configure common memory test interface by writing registers: + * MT_STOP_ON_ERROR, MT_DATA_PATTERN, MT_ADDR_PATTERN, MT_ADDR_BITS + */ + /* see MTC user guide */ + DDRCFG->MEM_TEST.MT_STOP_ON_ERROR.MT_STOP_ON_ERROR = 0U; + /* make sure off, will turn on later. */ + DDRCFG->MEM_TEST.MT_EN_SINGLE.MT_EN_SINGLE = 0x00U; + /* + * MT_DATA_PATTERN + * + * 0x00 => Counting pattern + * 0x01 => walking 1's + * 0x02 => pseudo random + * 0x03 => no repeating pseudo random + * 0x04 => alt 1's and 0's + * 0x05 => alt 5's and A's + * 0x06 => User specified + * 0x07 => pseudo random 16-bit + * 0x08 => pseudo random 8-bit + * 0x09- 0x0f reserved + * + */ + { + /* + * Added changing pattern so write pattern is different, read back + * can not pass on previously written data + */ + DDRCFG->MEM_TEST.MT_DATA_PATTERN.MT_DATA_PATTERN = data_pattern; + } + if(add_pattern == MTC_ADD_RANDOM) + { + /* + * MT_ADDR_PATTERN + * 0x00 => Count in pattern + * 0x01 => Pseudo Random Pattern + * 0x02 => Arbiatry Pattern Gen (user defined ) - Using RAMS + */ + DDRCFG->MEM_TEST.MT_ADDR_PATTERN.MT_ADDR_PATTERN = 1U; + } + else + { + DDRCFG->MEM_TEST.MT_ADDR_PATTERN.MT_ADDR_PATTERN = 0U; + } + } + + if(add_pattern != MTC_ADD_RANDOM) + { + /* + * Set the starting address and number to test + * + * MT_START_ADDR + * Starting address + * MT_ADRESS_BITS + * Length to test = 2 ** MT_ADRESS_BITS + */ + DDRCFG->MEM_TEST.MT_START_ADDR_0.MT_START_ADDR_0 =\ + (uint32_t)(start_address & 0xFFFFFFFFUL); + /* The address here is as see from DDR controller => start at 0x0*/ + DDRCFG->MEM_TEST.MT_START_ADDR_1.MT_START_ADDR_1 =\ + (uint32_t)((start_address >> 32U)); + } + else + { + DDRCFG->MEM_TEST.MT_START_ADDR_0.MT_START_ADDR_0 = 0U; + DDRCFG->MEM_TEST.MT_START_ADDR_1.MT_START_ADDR_1 = 0U; + } + DDRCFG->MEM_TEST.MT_ADDR_BITS.MT_ADDR_BITS =\ + size; /* 2 power 24 => 256k to do- make user programmable */ + + { + /* + * FOR each DQ lane + * set error mask registers MT_ERROR_MASK_* to mask out + * all error bits but the ones for the current DQ lane + * WHILE timeout counter is less than a threshold + * perform memory test by writing MT_EN or MT_EN_SINGLE + * wait for memory test completion by polling MT_DONE_ACK + * read back memory test error status from MT_ERROR_STS + * IF no error detected + * exit loop + * ELSE + * increment write calibration offset for current DQ lane + * by writing EXPERT_WRCALIB + * ENDWHILE + * ENDFOR + */ + { + /* + * MT_ERROR_MASK + * All bits set in this field mask corresponding bits in data fields + * i.e. mt_error and mt_error_hold will not be set for errors in + * those fields + * + * Structure of 144 bits same as DFI bus + * 36 bits per lane ( 8 physical * 4) + (1ECC * 4) = 36 + * + * If we wrote out the following pattern from software: + * 0x12345678 + * 0x87654321 + * 0x56789876 + * 0x43211234 + * We should see: + * NNNN_YXXX_XXX3_4YXX_XXXX_76YX_XXXX_X21Y_XXXX_XX78 + * N: not used + * Y: + */ + DDRCFG->MEM_TEST.MT_ERROR_MASK_0.MT_ERROR_MASK_0 = 0xFFFFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_1.MT_ERROR_MASK_1 = 0xFFFFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_2.MT_ERROR_MASK_2 = 0xFFFFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_3.MT_ERROR_MASK_3 = 0xFFFFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_4.MT_ERROR_MASK_4 = 0xFFFFFFFFU; + + if (mask & 0x1U) + { + DDRCFG->MEM_TEST.MT_ERROR_MASK_0.MT_ERROR_MASK_0 &= 0xFFFFFF00U; + DDRCFG->MEM_TEST.MT_ERROR_MASK_1.MT_ERROR_MASK_1 &= 0xFFFFF00FU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_2.MT_ERROR_MASK_2 &= 0xFFFF00FFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_3.MT_ERROR_MASK_3 &= 0xFFF00FFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_4.MT_ERROR_MASK_4 &= 0xFFFFFFFFU; + } + if (mask & 0x2U) + { + DDRCFG->MEM_TEST.MT_ERROR_MASK_0.MT_ERROR_MASK_0 &= 0xFFFF00FFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_1.MT_ERROR_MASK_1 &= 0xFFF00FFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_2.MT_ERROR_MASK_2 &= 0xFF00FFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_3.MT_ERROR_MASK_3 &= 0xF00FFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_4.MT_ERROR_MASK_4 &= 0xFFFFFFFFU; + } + if (mask & 0x4U) + { + DDRCFG->MEM_TEST.MT_ERROR_MASK_0.MT_ERROR_MASK_0 &= 0xFF00FFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_1.MT_ERROR_MASK_1 &= 0xF00FFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_2.MT_ERROR_MASK_2 &= 0x00FFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_3.MT_ERROR_MASK_3 &= 0x0FFFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_4.MT_ERROR_MASK_4 &= 0xFFFFFFF0U; + } + if (mask & 0x8U) + { + DDRCFG->MEM_TEST.MT_ERROR_MASK_0.MT_ERROR_MASK_0 &= 0x00FFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_1.MT_ERROR_MASK_1 &= 0x0FFFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_2.MT_ERROR_MASK_2 &= 0xFFFFFFF0U; + DDRCFG->MEM_TEST.MT_ERROR_MASK_3.MT_ERROR_MASK_3 &= 0xFFFFFF00U; + DDRCFG->MEM_TEST.MT_ERROR_MASK_4.MT_ERROR_MASK_4 &= 0xFFFFF00FU; + } + if (mask & 0x10U) + { + DDRCFG->MEM_TEST.MT_ERROR_MASK_0.MT_ERROR_MASK_0 &= 0xFFFFFFFFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_1.MT_ERROR_MASK_1 &= 0xFFFFFFF0U; + DDRCFG->MEM_TEST.MT_ERROR_MASK_2.MT_ERROR_MASK_2 &= 0xFFFFFF0FU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_3.MT_ERROR_MASK_3 &= 0xFFFFF0FFU; + DDRCFG->MEM_TEST.MT_ERROR_MASK_4.MT_ERROR_MASK_4 &= 0xFFFF0FFFU; + } + + /* + * MT_EN + * Enables memory test + * If asserted at end of memory test, will keep going + */ + DDRCFG->MEM_TEST.MT_EN.MT_EN = 0U; + /* + * MT_EN_SINGLE + * Will not repeat if this is set + */ + DDRCFG->MEM_TEST.MT_EN_SINGLE.MT_EN_SINGLE = 0x00U; + DDRCFG->MEM_TEST.MT_EN_SINGLE.MT_EN_SINGLE = 0x01U; + /* + * MT_DONE_ACK + * Set when test completes + */ + volatile uint64_t something_to_do = 0U; + #ifndef UNITTEST + while (( DDRCFG->MEM_TEST.MT_DONE_ACK.MT_DONE_ACK & 0x01U) == 0U) + { + something_to_do++; + if(something_to_do > 0xFFFFFFUL) + { +#ifdef DEBUG_DDR_INIT + (void)uprint32(g_debug_uart, "\n\rmtc test error:",MTC_TIMEOUT_ERROR); +#endif + return (MTC_TIMEOUT_ERROR); + } + #ifdef RENODE_DEBUG + break; + #endif + } + #endif + } + } + /* + * MT_ERROR_STS + * Return the error status + * todo:Check NWL data and detail error states here + */ + + return (DDRCFG->MEM_TEST.MT_ERROR_STS.MT_ERROR_STS & 0x01U); + +} + + +/***************************************************************************//** + * Setup DDRC + * These settings come from config tool + * + */ +#define _USE_SETTINGS_USED_IN_DDR3_FULL_CHIP_TEST + +static void init_ddrc(void) +{ + DDRCFG->ADDR_MAP.CFG_MANUAL_ADDRESS_MAP.CFG_MANUAL_ADDRESS_MAP =\ + LIBERO_SETTING_CFG_MANUAL_ADDRESS_MAP; + DDRCFG->ADDR_MAP.CFG_CHIPADDR_MAP.CFG_CHIPADDR_MAP =\ + LIBERO_SETTING_CFG_CHIPADDR_MAP; + DDRCFG->ADDR_MAP.CFG_CIDADDR_MAP.CFG_CIDADDR_MAP =\ + LIBERO_SETTING_CFG_CIDADDR_MAP; + DDRCFG->ADDR_MAP.CFG_MB_AUTOPCH_COL_BIT_POS_LOW.CFG_MB_AUTOPCH_COL_BIT_POS_LOW =\ + LIBERO_SETTING_CFG_MB_AUTOPCH_COL_BIT_POS_LOW; + DDRCFG->ADDR_MAP.CFG_MB_AUTOPCH_COL_BIT_POS_HIGH.CFG_MB_AUTOPCH_COL_BIT_POS_HIGH =\ + LIBERO_SETTING_CFG_MB_AUTOPCH_COL_BIT_POS_HIGH; + DDRCFG->ADDR_MAP.CFG_BANKADDR_MAP_0.CFG_BANKADDR_MAP_0 =\ + LIBERO_SETTING_CFG_BANKADDR_MAP_0; + DDRCFG->ADDR_MAP.CFG_BANKADDR_MAP_1.CFG_BANKADDR_MAP_1 =\ + LIBERO_SETTING_CFG_BANKADDR_MAP_1; + DDRCFG->ADDR_MAP.CFG_ROWADDR_MAP_0.CFG_ROWADDR_MAP_0 =\ + LIBERO_SETTING_CFG_ROWADDR_MAP_0; + DDRCFG->ADDR_MAP.CFG_ROWADDR_MAP_1.CFG_ROWADDR_MAP_1 =\ + LIBERO_SETTING_CFG_ROWADDR_MAP_1; + DDRCFG->ADDR_MAP.CFG_ROWADDR_MAP_2.CFG_ROWADDR_MAP_2 =\ + LIBERO_SETTING_CFG_ROWADDR_MAP_2; + DDRCFG->ADDR_MAP.CFG_ROWADDR_MAP_3.CFG_ROWADDR_MAP_3 =\ + LIBERO_SETTING_CFG_ROWADDR_MAP_3; + DDRCFG->ADDR_MAP.CFG_COLADDR_MAP_0.CFG_COLADDR_MAP_0 =\ + LIBERO_SETTING_CFG_COLADDR_MAP_0; + DDRCFG->ADDR_MAP.CFG_COLADDR_MAP_1.CFG_COLADDR_MAP_1 =\ + LIBERO_SETTING_CFG_COLADDR_MAP_1; + DDRCFG->ADDR_MAP.CFG_COLADDR_MAP_2.CFG_COLADDR_MAP_2 =\ + LIBERO_SETTING_CFG_COLADDR_MAP_2; + DDRCFG->MC_BASE3.CFG_VRCG_ENABLE.CFG_VRCG_ENABLE =\ + LIBERO_SETTING_CFG_VRCG_ENABLE; + DDRCFG->MC_BASE3.CFG_VRCG_DISABLE.CFG_VRCG_DISABLE =\ + LIBERO_SETTING_CFG_VRCG_DISABLE; + DDRCFG->MC_BASE3.CFG_WRITE_LATENCY_SET.CFG_WRITE_LATENCY_SET =\ + LIBERO_SETTING_CFG_WRITE_LATENCY_SET; + DDRCFG->MC_BASE3.CFG_THERMAL_OFFSET.CFG_THERMAL_OFFSET =\ + LIBERO_SETTING_CFG_THERMAL_OFFSET; + DDRCFG->MC_BASE3.CFG_SOC_ODT.CFG_SOC_ODT = LIBERO_SETTING_CFG_SOC_ODT; + DDRCFG->MC_BASE3.CFG_ODTE_CK.CFG_ODTE_CK = LIBERO_SETTING_CFG_ODTE_CK; + DDRCFG->MC_BASE3.CFG_ODTE_CS.CFG_ODTE_CS = LIBERO_SETTING_CFG_ODTE_CS; + DDRCFG->MC_BASE3.CFG_ODTD_CA.CFG_ODTD_CA = LIBERO_SETTING_CFG_ODTD_CA; + DDRCFG->MC_BASE3.CFG_LPDDR4_FSP_OP.CFG_LPDDR4_FSP_OP =\ + LIBERO_SETTING_CFG_LPDDR4_FSP_OP; + DDRCFG->MC_BASE3.CFG_GENERATE_REFRESH_ON_SRX.CFG_GENERATE_REFRESH_ON_SRX =\ + LIBERO_SETTING_CFG_GENERATE_REFRESH_ON_SRX; + DDRCFG->MC_BASE3.CFG_DBI_CL.CFG_DBI_CL = LIBERO_SETTING_CFG_DBI_CL; + DDRCFG->MC_BASE3.CFG_NON_DBI_CL.CFG_NON_DBI_CL =\ + LIBERO_SETTING_CFG_NON_DBI_CL; + DDRCFG->MC_BASE3.INIT_FORCE_WRITE_DATA_0.INIT_FORCE_WRITE_DATA_0 =\ + LIBERO_SETTING_INIT_FORCE_WRITE_DATA_0; + DDRCFG->MC_BASE1.CFG_WRITE_CRC.CFG_WRITE_CRC =\ + LIBERO_SETTING_CFG_WRITE_CRC; + DDRCFG->MC_BASE1.CFG_MPR_READ_FORMAT.CFG_MPR_READ_FORMAT =\ + LIBERO_SETTING_CFG_MPR_READ_FORMAT; + DDRCFG->MC_BASE1.CFG_WR_CMD_LAT_CRC_DM.CFG_WR_CMD_LAT_CRC_DM =\ + LIBERO_SETTING_CFG_WR_CMD_LAT_CRC_DM; + DDRCFG->MC_BASE1.CFG_FINE_GRAN_REF_MODE.CFG_FINE_GRAN_REF_MODE =\ + LIBERO_SETTING_CFG_FINE_GRAN_REF_MODE; + DDRCFG->MC_BASE1.CFG_TEMP_SENSOR_READOUT.CFG_TEMP_SENSOR_READOUT =\ + LIBERO_SETTING_CFG_TEMP_SENSOR_READOUT; + DDRCFG->MC_BASE1.CFG_PER_DRAM_ADDR_EN.CFG_PER_DRAM_ADDR_EN =\ + LIBERO_SETTING_CFG_PER_DRAM_ADDR_EN; + DDRCFG->MC_BASE1.CFG_GEARDOWN_MODE.CFG_GEARDOWN_MODE =\ + LIBERO_SETTING_CFG_GEARDOWN_MODE; + DDRCFG->MC_BASE1.CFG_WR_PREAMBLE.CFG_WR_PREAMBLE =\ + LIBERO_SETTING_CFG_WR_PREAMBLE; + DDRCFG->MC_BASE1.CFG_RD_PREAMBLE.CFG_RD_PREAMBLE =\ + LIBERO_SETTING_CFG_RD_PREAMBLE; + DDRCFG->MC_BASE1.CFG_RD_PREAMB_TRN_MODE.CFG_RD_PREAMB_TRN_MODE =\ + LIBERO_SETTING_CFG_RD_PREAMB_TRN_MODE; + DDRCFG->MC_BASE1.CFG_SR_ABORT.CFG_SR_ABORT = LIBERO_SETTING_CFG_SR_ABORT; + DDRCFG->MC_BASE1.CFG_CS_TO_CMDADDR_LATENCY.CFG_CS_TO_CMDADDR_LATENCY =\ + LIBERO_SETTING_CFG_CS_TO_CMDADDR_LATENCY; + DDRCFG->MC_BASE1.CFG_INT_VREF_MON.CFG_INT_VREF_MON =\ + LIBERO_SETTING_CFG_INT_VREF_MON; + DDRCFG->MC_BASE1.CFG_TEMP_CTRL_REF_MODE.CFG_TEMP_CTRL_REF_MODE =\ + LIBERO_SETTING_CFG_TEMP_CTRL_REF_MODE; + DDRCFG->MC_BASE1.CFG_TEMP_CTRL_REF_RANGE.CFG_TEMP_CTRL_REF_RANGE =\ + LIBERO_SETTING_CFG_TEMP_CTRL_REF_RANGE; + DDRCFG->MC_BASE1.CFG_MAX_PWR_DOWN_MODE.CFG_MAX_PWR_DOWN_MODE =\ + LIBERO_SETTING_CFG_MAX_PWR_DOWN_MODE; + DDRCFG->MC_BASE1.CFG_READ_DBI.CFG_READ_DBI = LIBERO_SETTING_CFG_READ_DBI; + DDRCFG->MC_BASE1.CFG_WRITE_DBI.CFG_WRITE_DBI =\ + LIBERO_SETTING_CFG_WRITE_DBI; + DDRCFG->MC_BASE1.CFG_DATA_MASK.CFG_DATA_MASK =\ + LIBERO_SETTING_CFG_DATA_MASK; + DDRCFG->MC_BASE1.CFG_CA_PARITY_PERSIST_ERR.CFG_CA_PARITY_PERSIST_ERR =\ + LIBERO_SETTING_CFG_CA_PARITY_PERSIST_ERR; + DDRCFG->MC_BASE1.CFG_RTT_PARK.CFG_RTT_PARK = LIBERO_SETTING_CFG_RTT_PARK; + DDRCFG->MC_BASE1.CFG_ODT_INBUF_4_PD.CFG_ODT_INBUF_4_PD =\ + LIBERO_SETTING_CFG_ODT_INBUF_4_PD; + DDRCFG->MC_BASE1.CFG_CA_PARITY_ERR_STATUS.CFG_CA_PARITY_ERR_STATUS =\ + LIBERO_SETTING_CFG_CA_PARITY_ERR_STATUS; + DDRCFG->MC_BASE1.CFG_CRC_ERROR_CLEAR.CFG_CRC_ERROR_CLEAR =\ + LIBERO_SETTING_CFG_CRC_ERROR_CLEAR; + DDRCFG->MC_BASE1.CFG_CA_PARITY_LATENCY.CFG_CA_PARITY_LATENCY =\ + LIBERO_SETTING_CFG_CA_PARITY_LATENCY; + DDRCFG->MC_BASE1.CFG_CCD_S.CFG_CCD_S = LIBERO_SETTING_CFG_CCD_S; + DDRCFG->MC_BASE1.CFG_CCD_L.CFG_CCD_L = LIBERO_SETTING_CFG_CCD_L; + DDRCFG->MC_BASE1.CFG_VREFDQ_TRN_ENABLE.CFG_VREFDQ_TRN_ENABLE =\ + LIBERO_SETTING_CFG_VREFDQ_TRN_ENABLE; + DDRCFG->MC_BASE1.CFG_VREFDQ_TRN_RANGE.CFG_VREFDQ_TRN_RANGE =\ + LIBERO_SETTING_CFG_VREFDQ_TRN_RANGE; + DDRCFG->MC_BASE1.CFG_VREFDQ_TRN_VALUE.CFG_VREFDQ_TRN_VALUE =\ + LIBERO_SETTING_CFG_VREFDQ_TRN_VALUE; + DDRCFG->MC_BASE1.CFG_RRD_S.CFG_RRD_S = LIBERO_SETTING_CFG_RRD_S; + DDRCFG->MC_BASE1.CFG_RRD_L.CFG_RRD_L = LIBERO_SETTING_CFG_RRD_L; + DDRCFG->MC_BASE1.CFG_WTR_S.CFG_WTR_S = LIBERO_SETTING_CFG_WTR_S; + DDRCFG->MC_BASE1.CFG_WTR_L.CFG_WTR_L = LIBERO_SETTING_CFG_WTR_L; + DDRCFG->MC_BASE1.CFG_WTR_S_CRC_DM.CFG_WTR_S_CRC_DM =\ + LIBERO_SETTING_CFG_WTR_S_CRC_DM; + DDRCFG->MC_BASE1.CFG_WTR_L_CRC_DM.CFG_WTR_L_CRC_DM =\ + LIBERO_SETTING_CFG_WTR_L_CRC_DM; + DDRCFG->MC_BASE1.CFG_WR_CRC_DM.CFG_WR_CRC_DM =\ + LIBERO_SETTING_CFG_WR_CRC_DM; + DDRCFG->MC_BASE1.CFG_RFC1.CFG_RFC1 = LIBERO_SETTING_CFG_RFC1; + DDRCFG->MC_BASE1.CFG_RFC2.CFG_RFC2 = LIBERO_SETTING_CFG_RFC2; + DDRCFG->MC_BASE1.CFG_RFC4.CFG_RFC4 = LIBERO_SETTING_CFG_RFC4; + DDRCFG->MC_BASE1.CFG_NIBBLE_DEVICES.CFG_NIBBLE_DEVICES =\ + LIBERO_SETTING_CFG_NIBBLE_DEVICES; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS0_0.CFG_BIT_MAP_INDEX_CS0_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS0_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS0_1.CFG_BIT_MAP_INDEX_CS0_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS0_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS1_0.CFG_BIT_MAP_INDEX_CS1_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS1_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS1_1.CFG_BIT_MAP_INDEX_CS1_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS1_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS2_0.CFG_BIT_MAP_INDEX_CS2_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS2_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS2_1.CFG_BIT_MAP_INDEX_CS2_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS2_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS3_0.CFG_BIT_MAP_INDEX_CS3_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS3_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS3_1.CFG_BIT_MAP_INDEX_CS3_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS3_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS4_0.CFG_BIT_MAP_INDEX_CS4_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS4_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS4_1.CFG_BIT_MAP_INDEX_CS4_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS4_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS5_0.CFG_BIT_MAP_INDEX_CS5_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS5_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS5_1.CFG_BIT_MAP_INDEX_CS5_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS5_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS6_0.CFG_BIT_MAP_INDEX_CS6_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS6_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS6_1.CFG_BIT_MAP_INDEX_CS6_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS6_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS7_0.CFG_BIT_MAP_INDEX_CS7_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS7_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS7_1.CFG_BIT_MAP_INDEX_CS7_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS7_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS8_0.CFG_BIT_MAP_INDEX_CS8_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS8_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS8_1.CFG_BIT_MAP_INDEX_CS8_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS8_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS9_0.CFG_BIT_MAP_INDEX_CS9_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS9_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS9_1.CFG_BIT_MAP_INDEX_CS9_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS9_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS10_0.CFG_BIT_MAP_INDEX_CS10_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS10_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS10_1.CFG_BIT_MAP_INDEX_CS10_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS10_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS11_0.CFG_BIT_MAP_INDEX_CS11_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS11_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS11_1.CFG_BIT_MAP_INDEX_CS11_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS11_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS12_0.CFG_BIT_MAP_INDEX_CS12_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS12_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS12_1.CFG_BIT_MAP_INDEX_CS12_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS12_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS13_0.CFG_BIT_MAP_INDEX_CS13_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS13_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS13_1.CFG_BIT_MAP_INDEX_CS13_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS13_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS14_0.CFG_BIT_MAP_INDEX_CS14_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS14_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS14_1.CFG_BIT_MAP_INDEX_CS14_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS14_1; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS15_0.CFG_BIT_MAP_INDEX_CS15_0 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS15_0; + DDRCFG->MC_BASE1.CFG_BIT_MAP_INDEX_CS15_1.CFG_BIT_MAP_INDEX_CS15_1 =\ + LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS15_1; + DDRCFG->MC_BASE1.CFG_NUM_LOGICAL_RANKS_PER_3DS.CFG_NUM_LOGICAL_RANKS_PER_3DS =\ + LIBERO_SETTING_CFG_NUM_LOGICAL_RANKS_PER_3DS; + DDRCFG->MC_BASE1.CFG_RFC_DLR1.CFG_RFC_DLR1 = LIBERO_SETTING_CFG_RFC_DLR1; + DDRCFG->MC_BASE1.CFG_RFC_DLR2.CFG_RFC_DLR2 = LIBERO_SETTING_CFG_RFC_DLR2; + DDRCFG->MC_BASE1.CFG_RFC_DLR4.CFG_RFC_DLR4 = LIBERO_SETTING_CFG_RFC_DLR4; + DDRCFG->MC_BASE1.CFG_RRD_DLR.CFG_RRD_DLR = LIBERO_SETTING_CFG_RRD_DLR; + DDRCFG->MC_BASE1.CFG_FAW_DLR.CFG_FAW_DLR = LIBERO_SETTING_CFG_FAW_DLR; + DDRCFG->MC_BASE1.CFG_ADVANCE_ACTIVATE_READY.CFG_ADVANCE_ACTIVATE_READY =\ + LIBERO_SETTING_CFG_ADVANCE_ACTIVATE_READY; + DDRCFG->MC_BASE2.CTRLR_SOFT_RESET_N.CTRLR_SOFT_RESET_N =\ + LIBERO_SETTING_CTRLR_SOFT_RESET_N; + DDRCFG->MC_BASE2.CFG_LOOKAHEAD_PCH.CFG_LOOKAHEAD_PCH =\ + LIBERO_SETTING_CFG_LOOKAHEAD_PCH; + DDRCFG->MC_BASE2.CFG_LOOKAHEAD_ACT.CFG_LOOKAHEAD_ACT =\ + LIBERO_SETTING_CFG_LOOKAHEAD_ACT; + DDRCFG->MC_BASE2.INIT_AUTOINIT_DISABLE.INIT_AUTOINIT_DISABLE =\ + LIBERO_SETTING_INIT_AUTOINIT_DISABLE; + DDRCFG->MC_BASE2.INIT_FORCE_RESET.INIT_FORCE_RESET =\ + LIBERO_SETTING_INIT_FORCE_RESET; + DDRCFG->MC_BASE2.INIT_GEARDOWN_EN.INIT_GEARDOWN_EN =\ + LIBERO_SETTING_INIT_GEARDOWN_EN; + DDRCFG->MC_BASE2.INIT_DISABLE_CKE.INIT_DISABLE_CKE =\ + LIBERO_SETTING_INIT_DISABLE_CKE; + DDRCFG->MC_BASE2.INIT_CS.INIT_CS = LIBERO_SETTING_INIT_CS; + DDRCFG->MC_BASE2.INIT_PRECHARGE_ALL.INIT_PRECHARGE_ALL =\ + LIBERO_SETTING_INIT_PRECHARGE_ALL; + DDRCFG->MC_BASE2.INIT_REFRESH.INIT_REFRESH = LIBERO_SETTING_INIT_REFRESH; + DDRCFG->MC_BASE2.INIT_ZQ_CAL_REQ.INIT_ZQ_CAL_REQ =\ + LIBERO_SETTING_INIT_ZQ_CAL_REQ; + DDRCFG->MC_BASE2.CFG_BL.CFG_BL = LIBERO_SETTING_CFG_BL; + DDRCFG->MC_BASE2.CTRLR_INIT.CTRLR_INIT = LIBERO_SETTING_CTRLR_INIT; + DDRCFG->MC_BASE2.CFG_AUTO_REF_EN.CFG_AUTO_REF_EN =\ + LIBERO_SETTING_CFG_AUTO_REF_EN; + DDRCFG->MC_BASE2.CFG_RAS.CFG_RAS = LIBERO_SETTING_CFG_RAS; + DDRCFG->MC_BASE2.CFG_RCD.CFG_RCD = LIBERO_SETTING_CFG_RCD; + DDRCFG->MC_BASE2.CFG_RRD.CFG_RRD = LIBERO_SETTING_CFG_RRD; + DDRCFG->MC_BASE2.CFG_RP.CFG_RP = LIBERO_SETTING_CFG_RP; + DDRCFG->MC_BASE2.CFG_RC.CFG_RC = LIBERO_SETTING_CFG_RC; + DDRCFG->MC_BASE2.CFG_FAW.CFG_FAW = LIBERO_SETTING_CFG_FAW; + DDRCFG->MC_BASE2.CFG_RFC.CFG_RFC = LIBERO_SETTING_CFG_RFC; + DDRCFG->MC_BASE2.CFG_RTP.CFG_RTP = LIBERO_SETTING_CFG_RTP; + DDRCFG->MC_BASE2.CFG_WR.CFG_WR = LIBERO_SETTING_CFG_WR; + DDRCFG->MC_BASE2.CFG_WTR.CFG_WTR = LIBERO_SETTING_CFG_WTR; + DDRCFG->MC_BASE2.CFG_PASR.CFG_PASR = LIBERO_SETTING_CFG_PASR; + DDRCFG->MC_BASE2.CFG_XP.CFG_XP = LIBERO_SETTING_CFG_XP; + DDRCFG->MC_BASE2.CFG_XSR.CFG_XSR = LIBERO_SETTING_CFG_XSR; + DDRCFG->MC_BASE2.CFG_CL.CFG_CL = LIBERO_SETTING_CFG_CL; + DDRCFG->MC_BASE2.CFG_READ_TO_WRITE.CFG_READ_TO_WRITE =\ + LIBERO_SETTING_CFG_READ_TO_WRITE; + DDRCFG->MC_BASE2.CFG_WRITE_TO_WRITE.CFG_WRITE_TO_WRITE =\ + LIBERO_SETTING_CFG_WRITE_TO_WRITE; + DDRCFG->MC_BASE2.CFG_READ_TO_READ.CFG_READ_TO_READ =\ + LIBERO_SETTING_CFG_READ_TO_READ; + DDRCFG->MC_BASE2.CFG_WRITE_TO_READ.CFG_WRITE_TO_READ =\ + LIBERO_SETTING_CFG_WRITE_TO_READ; + DDRCFG->MC_BASE2.CFG_READ_TO_WRITE_ODT.CFG_READ_TO_WRITE_ODT =\ + LIBERO_SETTING_CFG_READ_TO_WRITE_ODT; + DDRCFG->MC_BASE2.CFG_WRITE_TO_WRITE_ODT.CFG_WRITE_TO_WRITE_ODT =\ + LIBERO_SETTING_CFG_WRITE_TO_WRITE_ODT; + DDRCFG->MC_BASE2.CFG_READ_TO_READ_ODT.CFG_READ_TO_READ_ODT =\ + LIBERO_SETTING_CFG_READ_TO_READ_ODT; + DDRCFG->MC_BASE2.CFG_WRITE_TO_READ_ODT.CFG_WRITE_TO_READ_ODT =\ + LIBERO_SETTING_CFG_WRITE_TO_READ_ODT; + DDRCFG->MC_BASE2.CFG_MIN_READ_IDLE.CFG_MIN_READ_IDLE =\ + LIBERO_SETTING_CFG_MIN_READ_IDLE; + DDRCFG->MC_BASE2.CFG_MRD.CFG_MRD = LIBERO_SETTING_CFG_MRD; + DDRCFG->MC_BASE2.CFG_BT.CFG_BT = LIBERO_SETTING_CFG_BT; + DDRCFG->MC_BASE2.CFG_DS.CFG_DS = LIBERO_SETTING_CFG_DS; + DDRCFG->MC_BASE2.CFG_QOFF.CFG_QOFF = LIBERO_SETTING_CFG_QOFF; + DDRCFG->MC_BASE2.CFG_RTT.CFG_RTT = LIBERO_SETTING_CFG_RTT; + DDRCFG->MC_BASE2.CFG_DLL_DISABLE.CFG_DLL_DISABLE =\ + LIBERO_SETTING_CFG_DLL_DISABLE; + DDRCFG->MC_BASE2.CFG_REF_PER.CFG_REF_PER = LIBERO_SETTING_CFG_REF_PER; + DDRCFG->MC_BASE2.CFG_STARTUP_DELAY.CFG_STARTUP_DELAY =\ + LIBERO_SETTING_CFG_STARTUP_DELAY; + DDRCFG->MC_BASE2.CFG_MEM_COLBITS.CFG_MEM_COLBITS =\ + LIBERO_SETTING_CFG_MEM_COLBITS; + DDRCFG->MC_BASE2.CFG_MEM_ROWBITS.CFG_MEM_ROWBITS =\ + LIBERO_SETTING_CFG_MEM_ROWBITS; + DDRCFG->MC_BASE2.CFG_MEM_BANKBITS.CFG_MEM_BANKBITS =\ + LIBERO_SETTING_CFG_MEM_BANKBITS; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS0.CFG_ODT_RD_MAP_CS0 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS0; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS1.CFG_ODT_RD_MAP_CS1 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS1; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS2.CFG_ODT_RD_MAP_CS2 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS2; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS3.CFG_ODT_RD_MAP_CS3 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS3; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS4.CFG_ODT_RD_MAP_CS4 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS4; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS5.CFG_ODT_RD_MAP_CS5 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS5; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS6.CFG_ODT_RD_MAP_CS6 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS6; + DDRCFG->MC_BASE2.CFG_ODT_RD_MAP_CS7.CFG_ODT_RD_MAP_CS7 =\ + LIBERO_SETTING_CFG_ODT_RD_MAP_CS7; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS0.CFG_ODT_WR_MAP_CS0 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS0; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS1.CFG_ODT_WR_MAP_CS1 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS1; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS2.CFG_ODT_WR_MAP_CS2 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS2; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS3.CFG_ODT_WR_MAP_CS3 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS3; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS4.CFG_ODT_WR_MAP_CS4 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS4; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS5.CFG_ODT_WR_MAP_CS5 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS5; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS6.CFG_ODT_WR_MAP_CS6 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS6; + DDRCFG->MC_BASE2.CFG_ODT_WR_MAP_CS7.CFG_ODT_WR_MAP_CS7 =\ + LIBERO_SETTING_CFG_ODT_WR_MAP_CS7; + DDRCFG->MC_BASE2.CFG_ODT_RD_TURN_ON.CFG_ODT_RD_TURN_ON =\ + LIBERO_SETTING_CFG_ODT_RD_TURN_ON; + DDRCFG->MC_BASE2.CFG_ODT_WR_TURN_ON.CFG_ODT_WR_TURN_ON =\ + LIBERO_SETTING_CFG_ODT_WR_TURN_ON; + DDRCFG->MC_BASE2.CFG_ODT_RD_TURN_OFF.CFG_ODT_RD_TURN_OFF =\ + LIBERO_SETTING_CFG_ODT_RD_TURN_OFF; + DDRCFG->MC_BASE2.CFG_ODT_WR_TURN_OFF.CFG_ODT_WR_TURN_OFF =\ + LIBERO_SETTING_CFG_ODT_WR_TURN_OFF; + DDRCFG->MC_BASE2.CFG_EMR3.CFG_EMR3 = LIBERO_SETTING_CFG_EMR3; + DDRCFG->MC_BASE2.CFG_TWO_T.CFG_TWO_T = LIBERO_SETTING_CFG_TWO_T; + DDRCFG->MC_BASE2.CFG_TWO_T_SEL_CYCLE.CFG_TWO_T_SEL_CYCLE =\ + LIBERO_SETTING_CFG_TWO_T_SEL_CYCLE; + DDRCFG->MC_BASE2.CFG_REGDIMM.CFG_REGDIMM = LIBERO_SETTING_CFG_REGDIMM; + DDRCFG->MC_BASE2.CFG_MOD.CFG_MOD = LIBERO_SETTING_CFG_MOD; + DDRCFG->MC_BASE2.CFG_XS.CFG_XS = LIBERO_SETTING_CFG_XS; + DDRCFG->MC_BASE2.CFG_XSDLL.CFG_XSDLL = LIBERO_SETTING_CFG_XSDLL; + DDRCFG->MC_BASE2.CFG_XPR.CFG_XPR = LIBERO_SETTING_CFG_XPR; + DDRCFG->MC_BASE2.CFG_AL_MODE.CFG_AL_MODE = LIBERO_SETTING_CFG_AL_MODE; + DDRCFG->MC_BASE2.CFG_CWL.CFG_CWL = LIBERO_SETTING_CFG_CWL; + DDRCFG->MC_BASE2.CFG_BL_MODE.CFG_BL_MODE = LIBERO_SETTING_CFG_BL_MODE; + DDRCFG->MC_BASE2.CFG_TDQS.CFG_TDQS = LIBERO_SETTING_CFG_TDQS; + DDRCFG->MC_BASE2.CFG_RTT_WR.CFG_RTT_WR = LIBERO_SETTING_CFG_RTT_WR; + DDRCFG->MC_BASE2.CFG_LP_ASR.CFG_LP_ASR = LIBERO_SETTING_CFG_LP_ASR; + DDRCFG->MC_BASE2.CFG_AUTO_SR.CFG_AUTO_SR = LIBERO_SETTING_CFG_AUTO_SR; + DDRCFG->MC_BASE2.CFG_SRT.CFG_SRT = LIBERO_SETTING_CFG_SRT; + DDRCFG->MC_BASE2.CFG_ADDR_MIRROR.CFG_ADDR_MIRROR =\ + LIBERO_SETTING_CFG_ADDR_MIRROR; + DDRCFG->MC_BASE2.CFG_ZQ_CAL_TYPE.CFG_ZQ_CAL_TYPE =\ + LIBERO_SETTING_CFG_ZQ_CAL_TYPE; + DDRCFG->MC_BASE2.CFG_ZQ_CAL_PER.CFG_ZQ_CAL_PER =\ + LIBERO_SETTING_CFG_ZQ_CAL_PER; + DDRCFG->MC_BASE2.CFG_AUTO_ZQ_CAL_EN.CFG_AUTO_ZQ_CAL_EN =\ + LIBERO_SETTING_CFG_AUTO_ZQ_CAL_EN; + DDRCFG->MC_BASE2.CFG_MEMORY_TYPE.CFG_MEMORY_TYPE =\ + LIBERO_SETTING_CFG_MEMORY_TYPE; + DDRCFG->MC_BASE2.CFG_ONLY_SRANK_CMDS.CFG_ONLY_SRANK_CMDS =\ + LIBERO_SETTING_CFG_ONLY_SRANK_CMDS; + DDRCFG->MC_BASE2.CFG_NUM_RANKS.CFG_NUM_RANKS =\ + LIBERO_SETTING_CFG_NUM_RANKS; + DDRCFG->MC_BASE2.CFG_QUAD_RANK.CFG_QUAD_RANK =\ + LIBERO_SETTING_CFG_QUAD_RANK; + DDRCFG->MC_BASE2.CFG_EARLY_RANK_TO_WR_START.CFG_EARLY_RANK_TO_WR_START =\ + LIBERO_SETTING_CFG_EARLY_RANK_TO_WR_START; + DDRCFG->MC_BASE2.CFG_EARLY_RANK_TO_RD_START.CFG_EARLY_RANK_TO_RD_START =\ + LIBERO_SETTING_CFG_EARLY_RANK_TO_RD_START; + DDRCFG->MC_BASE2.CFG_PASR_BANK.CFG_PASR_BANK =\ + LIBERO_SETTING_CFG_PASR_BANK; + DDRCFG->MC_BASE2.CFG_PASR_SEG.CFG_PASR_SEG = LIBERO_SETTING_CFG_PASR_SEG; + DDRCFG->MC_BASE2.INIT_MRR_MODE.INIT_MRR_MODE =\ + LIBERO_SETTING_INIT_MRR_MODE; + DDRCFG->MC_BASE2.INIT_MR_W_REQ.INIT_MR_W_REQ =\ + LIBERO_SETTING_INIT_MR_W_REQ; + DDRCFG->MC_BASE2.INIT_MR_ADDR.INIT_MR_ADDR = LIBERO_SETTING_INIT_MR_ADDR; + DDRCFG->MC_BASE2.INIT_MR_WR_DATA.INIT_MR_WR_DATA =\ + LIBERO_SETTING_INIT_MR_WR_DATA; + DDRCFG->MC_BASE2.INIT_MR_WR_MASK.INIT_MR_WR_MASK =\ + LIBERO_SETTING_INIT_MR_WR_MASK; + DDRCFG->MC_BASE2.INIT_NOP.INIT_NOP = LIBERO_SETTING_INIT_NOP; + DDRCFG->MC_BASE2.CFG_INIT_DURATION.CFG_INIT_DURATION =\ + LIBERO_SETTING_CFG_INIT_DURATION; + DDRCFG->MC_BASE2.CFG_ZQINIT_CAL_DURATION.CFG_ZQINIT_CAL_DURATION =\ + LIBERO_SETTING_CFG_ZQINIT_CAL_DURATION; + DDRCFG->MC_BASE2.CFG_ZQ_CAL_L_DURATION.CFG_ZQ_CAL_L_DURATION =\ + LIBERO_SETTING_CFG_ZQ_CAL_L_DURATION; + DDRCFG->MC_BASE2.CFG_ZQ_CAL_S_DURATION.CFG_ZQ_CAL_S_DURATION =\ + LIBERO_SETTING_CFG_ZQ_CAL_S_DURATION; + DDRCFG->MC_BASE2.CFG_ZQ_CAL_R_DURATION.CFG_ZQ_CAL_R_DURATION =\ + LIBERO_SETTING_CFG_ZQ_CAL_R_DURATION; + DDRCFG->MC_BASE2.CFG_MRR.CFG_MRR = LIBERO_SETTING_CFG_MRR; + DDRCFG->MC_BASE2.CFG_MRW.CFG_MRW = LIBERO_SETTING_CFG_MRW; + DDRCFG->MC_BASE2.CFG_ODT_POWERDOWN.CFG_ODT_POWERDOWN =\ + LIBERO_SETTING_CFG_ODT_POWERDOWN; + DDRCFG->MC_BASE2.CFG_WL.CFG_WL = LIBERO_SETTING_CFG_WL; + DDRCFG->MC_BASE2.CFG_RL.CFG_RL = LIBERO_SETTING_CFG_RL; + DDRCFG->MC_BASE2.CFG_CAL_READ_PERIOD.CFG_CAL_READ_PERIOD =\ + LIBERO_SETTING_CFG_CAL_READ_PERIOD; + DDRCFG->MC_BASE2.CFG_NUM_CAL_READS.CFG_NUM_CAL_READS =\ + LIBERO_SETTING_CFG_NUM_CAL_READS; + DDRCFG->MC_BASE2.INIT_SELF_REFRESH.INIT_SELF_REFRESH =\ + LIBERO_SETTING_INIT_SELF_REFRESH; + DDRCFG->MC_BASE2.INIT_POWER_DOWN.INIT_POWER_DOWN =\ + LIBERO_SETTING_INIT_POWER_DOWN; + DDRCFG->MC_BASE2.INIT_FORCE_WRITE.INIT_FORCE_WRITE =\ + LIBERO_SETTING_INIT_FORCE_WRITE; + DDRCFG->MC_BASE2.INIT_FORCE_WRITE_CS.INIT_FORCE_WRITE_CS =\ + LIBERO_SETTING_INIT_FORCE_WRITE_CS; + DDRCFG->MC_BASE2.CFG_CTRLR_INIT_DISABLE.CFG_CTRLR_INIT_DISABLE =\ + LIBERO_SETTING_CFG_CTRLR_INIT_DISABLE; + DDRCFG->MC_BASE2.INIT_RDIMM_COMPLETE.INIT_RDIMM_COMPLETE =\ + LIBERO_SETTING_INIT_RDIMM_COMPLETE; + DDRCFG->MC_BASE2.CFG_RDIMM_LAT.CFG_RDIMM_LAT =\ + LIBERO_SETTING_CFG_RDIMM_LAT; + DDRCFG->MC_BASE2.CFG_RDIMM_BSIDE_INVERT.CFG_RDIMM_BSIDE_INVERT =\ + LIBERO_SETTING_CFG_RDIMM_BSIDE_INVERT; + DDRCFG->MC_BASE2.CFG_LRDIMM.CFG_LRDIMM = LIBERO_SETTING_CFG_LRDIMM; + DDRCFG->MC_BASE2.INIT_MEMORY_RESET_MASK.INIT_MEMORY_RESET_MASK =\ + LIBERO_SETTING_INIT_MEMORY_RESET_MASK; + DDRCFG->MC_BASE2.CFG_RD_PREAMB_TOGGLE.CFG_RD_PREAMB_TOGGLE =\ + LIBERO_SETTING_CFG_RD_PREAMB_TOGGLE; + DDRCFG->MC_BASE2.CFG_RD_POSTAMBLE.CFG_RD_POSTAMBLE =\ + LIBERO_SETTING_CFG_RD_POSTAMBLE; + DDRCFG->MC_BASE2.CFG_PU_CAL.CFG_PU_CAL = LIBERO_SETTING_CFG_PU_CAL; + DDRCFG->MC_BASE2.CFG_DQ_ODT.CFG_DQ_ODT = LIBERO_SETTING_CFG_DQ_ODT; + DDRCFG->MC_BASE2.CFG_CA_ODT.CFG_CA_ODT = LIBERO_SETTING_CFG_CA_ODT; + DDRCFG->MC_BASE2.CFG_ZQLATCH_DURATION.CFG_ZQLATCH_DURATION =\ + LIBERO_SETTING_CFG_ZQLATCH_DURATION; + DDRCFG->MC_BASE2.INIT_CAL_SELECT.INIT_CAL_SELECT =\ + LIBERO_SETTING_INIT_CAL_SELECT; + DDRCFG->MC_BASE2.INIT_CAL_L_R_REQ.INIT_CAL_L_R_REQ =\ + LIBERO_SETTING_INIT_CAL_L_R_REQ; + DDRCFG->MC_BASE2.INIT_CAL_L_B_SIZE.INIT_CAL_L_B_SIZE =\ + LIBERO_SETTING_INIT_CAL_L_B_SIZE; + DDRCFG->MC_BASE2.INIT_RWFIFO.INIT_RWFIFO = LIBERO_SETTING_INIT_RWFIFO; + DDRCFG->MC_BASE2.INIT_RD_DQCAL.INIT_RD_DQCAL =\ + LIBERO_SETTING_INIT_RD_DQCAL; + DDRCFG->MC_BASE2.INIT_START_DQSOSC.INIT_START_DQSOSC =\ + LIBERO_SETTING_INIT_START_DQSOSC; + DDRCFG->MC_BASE2.INIT_STOP_DQSOSC.INIT_STOP_DQSOSC =\ + LIBERO_SETTING_INIT_STOP_DQSOSC; + DDRCFG->MC_BASE2.INIT_ZQ_CAL_START.INIT_ZQ_CAL_START =\ + LIBERO_SETTING_INIT_ZQ_CAL_START; + DDRCFG->MC_BASE2.CFG_WR_POSTAMBLE.CFG_WR_POSTAMBLE =\ + LIBERO_SETTING_CFG_WR_POSTAMBLE; + DDRCFG->MC_BASE2.INIT_CAL_L_ADDR_0.INIT_CAL_L_ADDR_0 =\ + LIBERO_SETTING_INIT_CAL_L_ADDR_0; + DDRCFG->MC_BASE2.INIT_CAL_L_ADDR_1.INIT_CAL_L_ADDR_1 =\ + LIBERO_SETTING_INIT_CAL_L_ADDR_1; + DDRCFG->MC_BASE2.CFG_CTRLUPD_TRIG.CFG_CTRLUPD_TRIG =\ + LIBERO_SETTING_CFG_CTRLUPD_TRIG; + DDRCFG->MC_BASE2.CFG_CTRLUPD_START_DELAY.CFG_CTRLUPD_START_DELAY =\ + LIBERO_SETTING_CFG_CTRLUPD_START_DELAY; + DDRCFG->MC_BASE2.CFG_DFI_T_CTRLUPD_MAX.CFG_DFI_T_CTRLUPD_MAX =\ + LIBERO_SETTING_CFG_DFI_T_CTRLUPD_MAX; + DDRCFG->MC_BASE2.CFG_CTRLR_BUSY_SEL.CFG_CTRLR_BUSY_SEL =\ + LIBERO_SETTING_CFG_CTRLR_BUSY_SEL; + DDRCFG->MC_BASE2.CFG_CTRLR_BUSY_VALUE.CFG_CTRLR_BUSY_VALUE =\ + LIBERO_SETTING_CFG_CTRLR_BUSY_VALUE; + DDRCFG->MC_BASE2.CFG_CTRLR_BUSY_TURN_OFF_DELAY.CFG_CTRLR_BUSY_TURN_OFF_DELAY =\ + LIBERO_SETTING_CFG_CTRLR_BUSY_TURN_OFF_DELAY; + DDRCFG->MC_BASE2.CFG_CTRLR_BUSY_SLOW_RESTART_WINDOW.CFG_CTRLR_BUSY_SLOW_RESTART_WINDOW =\ + LIBERO_SETTING_CFG_CTRLR_BUSY_SLOW_RESTART_WINDOW; + DDRCFG->MC_BASE2.CFG_CTRLR_BUSY_RESTART_HOLDOFF.CFG_CTRLR_BUSY_RESTART_HOLDOFF =\ + LIBERO_SETTING_CFG_CTRLR_BUSY_RESTART_HOLDOFF; + DDRCFG->MC_BASE2.CFG_PARITY_RDIMM_DELAY.CFG_PARITY_RDIMM_DELAY =\ + LIBERO_SETTING_CFG_PARITY_RDIMM_DELAY; + DDRCFG->MC_BASE2.CFG_CTRLR_BUSY_ENABLE.CFG_CTRLR_BUSY_ENABLE =\ + LIBERO_SETTING_CFG_CTRLR_BUSY_ENABLE; + DDRCFG->MC_BASE2.CFG_ASYNC_ODT.CFG_ASYNC_ODT =\ + LIBERO_SETTING_CFG_ASYNC_ODT; + DDRCFG->MC_BASE2.CFG_ZQ_CAL_DURATION.CFG_ZQ_CAL_DURATION =\ + LIBERO_SETTING_CFG_ZQ_CAL_DURATION; + DDRCFG->MC_BASE2.CFG_MRRI.CFG_MRRI = LIBERO_SETTING_CFG_MRRI; + DDRCFG->MC_BASE2.INIT_ODT_FORCE_EN.INIT_ODT_FORCE_EN =\ + LIBERO_SETTING_INIT_ODT_FORCE_EN; + DDRCFG->MC_BASE2.INIT_ODT_FORCE_RANK.INIT_ODT_FORCE_RANK =\ + LIBERO_SETTING_INIT_ODT_FORCE_RANK; + DDRCFG->MC_BASE2.CFG_PHYUPD_ACK_DELAY.CFG_PHYUPD_ACK_DELAY =\ + LIBERO_SETTING_CFG_PHYUPD_ACK_DELAY; + DDRCFG->MC_BASE2.CFG_MIRROR_X16_BG0_BG1.CFG_MIRROR_X16_BG0_BG1 =\ + LIBERO_SETTING_CFG_MIRROR_X16_BG0_BG1; + DDRCFG->MC_BASE2.INIT_PDA_MR_W_REQ.INIT_PDA_MR_W_REQ =\ + LIBERO_SETTING_INIT_PDA_MR_W_REQ; + DDRCFG->MC_BASE2.INIT_PDA_NIBBLE_SELECT.INIT_PDA_NIBBLE_SELECT =\ + LIBERO_SETTING_INIT_PDA_NIBBLE_SELECT; + DDRCFG->MC_BASE2.CFG_DRAM_CLK_DISABLE_IN_SELF_REFRESH.CFG_DRAM_CLK_DISABLE_IN_SELF_REFRESH =\ + LIBERO_SETTING_CFG_DRAM_CLK_DISABLE_IN_SELF_REFRESH; + DDRCFG->MC_BASE2.CFG_CKSRE.CFG_CKSRE = LIBERO_SETTING_CFG_CKSRE; + DDRCFG->MC_BASE2.CFG_CKSRX.CFG_CKSRX = LIBERO_SETTING_CFG_CKSRX; + DDRCFG->MC_BASE2.CFG_RCD_STAB.CFG_RCD_STAB = LIBERO_SETTING_CFG_RCD_STAB; + DDRCFG->MC_BASE2.CFG_DFI_T_CTRL_DELAY.CFG_DFI_T_CTRL_DELAY =\ + LIBERO_SETTING_CFG_DFI_T_CTRL_DELAY; + DDRCFG->MC_BASE2.CFG_DFI_T_DRAM_CLK_ENABLE.CFG_DFI_T_DRAM_CLK_ENABLE =\ + LIBERO_SETTING_CFG_DFI_T_DRAM_CLK_ENABLE; + DDRCFG->MC_BASE2.CFG_IDLE_TIME_TO_SELF_REFRESH.CFG_IDLE_TIME_TO_SELF_REFRESH =\ + LIBERO_SETTING_CFG_IDLE_TIME_TO_SELF_REFRESH; + DDRCFG->MC_BASE2.CFG_IDLE_TIME_TO_POWER_DOWN.CFG_IDLE_TIME_TO_POWER_DOWN =\ + LIBERO_SETTING_CFG_IDLE_TIME_TO_POWER_DOWN; + DDRCFG->MC_BASE2.CFG_BURST_RW_REFRESH_HOLDOFF.CFG_BURST_RW_REFRESH_HOLDOFF =\ + LIBERO_SETTING_CFG_BURST_RW_REFRESH_HOLDOFF; + DDRCFG->MC_BASE2.CFG_BG_INTERLEAVE.CFG_BG_INTERLEAVE =\ + LIBERO_SETTING_CFG_BG_INTERLEAVE; + DDRCFG->MC_BASE2.CFG_REFRESH_DURING_PHY_TRAINING.CFG_REFRESH_DURING_PHY_TRAINING =\ + LIBERO_SETTING_CFG_REFRESH_DURING_PHY_TRAINING; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P0.CFG_STARVE_TIMEOUT_P0 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P0; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P1.CFG_STARVE_TIMEOUT_P1 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P1; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P2.CFG_STARVE_TIMEOUT_P2 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P2; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P3.CFG_STARVE_TIMEOUT_P3 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P3; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P4.CFG_STARVE_TIMEOUT_P4 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P4; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P5.CFG_STARVE_TIMEOUT_P5 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P5; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P6.CFG_STARVE_TIMEOUT_P6 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P6; + DDRCFG->MPFE.CFG_STARVE_TIMEOUT_P7.CFG_STARVE_TIMEOUT_P7 =\ + LIBERO_SETTING_CFG_STARVE_TIMEOUT_P7; + DDRCFG->REORDER.CFG_REORDER_EN.CFG_REORDER_EN =\ + LIBERO_SETTING_CFG_REORDER_EN; + DDRCFG->REORDER.CFG_REORDER_QUEUE_EN.CFG_REORDER_QUEUE_EN =\ + LIBERO_SETTING_CFG_REORDER_QUEUE_EN; + DDRCFG->REORDER.CFG_INTRAPORT_REORDER_EN.CFG_INTRAPORT_REORDER_EN =\ + LIBERO_SETTING_CFG_INTRAPORT_REORDER_EN; + DDRCFG->REORDER.CFG_MAINTAIN_COHERENCY.CFG_MAINTAIN_COHERENCY =\ + LIBERO_SETTING_CFG_MAINTAIN_COHERENCY; + DDRCFG->REORDER.CFG_Q_AGE_LIMIT.CFG_Q_AGE_LIMIT =\ + LIBERO_SETTING_CFG_Q_AGE_LIMIT; + DDRCFG->REORDER.CFG_RO_CLOSED_PAGE_POLICY.CFG_RO_CLOSED_PAGE_POLICY =\ + LIBERO_SETTING_CFG_RO_CLOSED_PAGE_POLICY; + DDRCFG->REORDER.CFG_REORDER_RW_ONLY.CFG_REORDER_RW_ONLY =\ + LIBERO_SETTING_CFG_REORDER_RW_ONLY; + DDRCFG->REORDER.CFG_RO_PRIORITY_EN.CFG_RO_PRIORITY_EN =\ + LIBERO_SETTING_CFG_RO_PRIORITY_EN; + DDRCFG->RMW.CFG_DM_EN.CFG_DM_EN = LIBERO_SETTING_CFG_DM_EN; + DDRCFG->RMW.CFG_RMW_EN.CFG_RMW_EN = LIBERO_SETTING_CFG_RMW_EN; + DDRCFG->ECC.CFG_ECC_CORRECTION_EN.CFG_ECC_CORRECTION_EN =\ + LIBERO_SETTING_CFG_ECC_CORRECTION_EN; + DDRCFG->ECC.CFG_ECC_BYPASS.CFG_ECC_BYPASS = LIBERO_SETTING_CFG_ECC_BYPASS; + DDRCFG->ECC.INIT_WRITE_DATA_1B_ECC_ERROR_GEN.INIT_WRITE_DATA_1B_ECC_ERROR_GEN =\ + LIBERO_SETTING_INIT_WRITE_DATA_1B_ECC_ERROR_GEN; + DDRCFG->ECC.INIT_WRITE_DATA_2B_ECC_ERROR_GEN.INIT_WRITE_DATA_2B_ECC_ERROR_GEN =\ + LIBERO_SETTING_INIT_WRITE_DATA_2B_ECC_ERROR_GEN; + DDRCFG->ECC.CFG_ECC_1BIT_INT_THRESH.CFG_ECC_1BIT_INT_THRESH =\ + LIBERO_SETTING_CFG_ECC_1BIT_INT_THRESH; + DDRCFG->READ_CAPT.INIT_READ_CAPTURE_ADDR.INIT_READ_CAPTURE_ADDR =\ + LIBERO_SETTING_INIT_READ_CAPTURE_ADDR; + DDRCFG->MTA.CFG_ERROR_GROUP_SEL.CFG_ERROR_GROUP_SEL =\ + LIBERO_SETTING_CFG_ERROR_GROUP_SEL; + DDRCFG->MTA.CFG_DATA_SEL.CFG_DATA_SEL = LIBERO_SETTING_CFG_DATA_SEL; + DDRCFG->MTA.CFG_TRIG_MODE.CFG_TRIG_MODE = LIBERO_SETTING_CFG_TRIG_MODE; + DDRCFG->MTA.CFG_POST_TRIG_CYCS.CFG_POST_TRIG_CYCS =\ + LIBERO_SETTING_CFG_POST_TRIG_CYCS; + DDRCFG->MTA.CFG_TRIG_MASK.CFG_TRIG_MASK = LIBERO_SETTING_CFG_TRIG_MASK; + DDRCFG->MTA.CFG_EN_MASK.CFG_EN_MASK = LIBERO_SETTING_CFG_EN_MASK; + DDRCFG->MTA.MTC_ACQ_ADDR.MTC_ACQ_ADDR = LIBERO_SETTING_MTC_ACQ_ADDR; + DDRCFG->MTA.CFG_TRIG_MT_ADDR_0.CFG_TRIG_MT_ADDR_0 =\ + LIBERO_SETTING_CFG_TRIG_MT_ADDR_0; + DDRCFG->MTA.CFG_TRIG_MT_ADDR_1.CFG_TRIG_MT_ADDR_1 =\ + LIBERO_SETTING_CFG_TRIG_MT_ADDR_1; + DDRCFG->MTA.CFG_TRIG_ERR_MASK_0.CFG_TRIG_ERR_MASK_0 =\ + LIBERO_SETTING_CFG_TRIG_ERR_MASK_0; + DDRCFG->MTA.CFG_TRIG_ERR_MASK_1.CFG_TRIG_ERR_MASK_1 =\ + LIBERO_SETTING_CFG_TRIG_ERR_MASK_1; + DDRCFG->MTA.CFG_TRIG_ERR_MASK_2.CFG_TRIG_ERR_MASK_2 =\ + LIBERO_SETTING_CFG_TRIG_ERR_MASK_2; + DDRCFG->MTA.CFG_TRIG_ERR_MASK_3.CFG_TRIG_ERR_MASK_3 =\ + LIBERO_SETTING_CFG_TRIG_ERR_MASK_3; + DDRCFG->MTA.CFG_TRIG_ERR_MASK_4.CFG_TRIG_ERR_MASK_4 =\ + LIBERO_SETTING_CFG_TRIG_ERR_MASK_4; + DDRCFG->MTA.MTC_ACQ_WR_DATA_0.MTC_ACQ_WR_DATA_0 =\ + LIBERO_SETTING_MTC_ACQ_WR_DATA_0; + DDRCFG->MTA.MTC_ACQ_WR_DATA_1.MTC_ACQ_WR_DATA_1 =\ + LIBERO_SETTING_MTC_ACQ_WR_DATA_1; + DDRCFG->MTA.MTC_ACQ_WR_DATA_2.MTC_ACQ_WR_DATA_2 =\ + LIBERO_SETTING_MTC_ACQ_WR_DATA_2; + DDRCFG->MTA.CFG_PRE_TRIG_CYCS.CFG_PRE_TRIG_CYCS =\ + LIBERO_SETTING_CFG_PRE_TRIG_CYCS; + DDRCFG->MTA.CFG_DATA_SEL_FIRST_ERROR.CFG_DATA_SEL_FIRST_ERROR =\ + LIBERO_SETTING_CFG_DATA_SEL_FIRST_ERROR; + DDRCFG->DYN_WIDTH_ADJ.CFG_DQ_WIDTH.CFG_DQ_WIDTH =\ + LIBERO_SETTING_CFG_DQ_WIDTH; + DDRCFG->DYN_WIDTH_ADJ.CFG_ACTIVE_DQ_SEL.CFG_ACTIVE_DQ_SEL =\ + LIBERO_SETTING_CFG_ACTIVE_DQ_SEL; + DDRCFG->CA_PAR_ERR.INIT_CA_PARITY_ERROR_GEN_REQ.INIT_CA_PARITY_ERROR_GEN_REQ =\ + LIBERO_SETTING_INIT_CA_PARITY_ERROR_GEN_REQ; + DDRCFG->CA_PAR_ERR.INIT_CA_PARITY_ERROR_GEN_CMD.INIT_CA_PARITY_ERROR_GEN_CMD =\ + LIBERO_SETTING_INIT_CA_PARITY_ERROR_GEN_CMD; + DDRCFG->DFI.CFG_DFI_T_RDDATA_EN.CFG_DFI_T_RDDATA_EN =\ + LIBERO_SETTING_CFG_DFI_T_RDDATA_EN; + DDRCFG->DFI.CFG_DFI_T_PHY_RDLAT.CFG_DFI_T_PHY_RDLAT =\ + LIBERO_SETTING_CFG_DFI_T_PHY_RDLAT; + DDRCFG->DFI.CFG_DFI_T_PHY_WRLAT.CFG_DFI_T_PHY_WRLAT =\ + LIBERO_SETTING_CFG_DFI_T_PHY_WRLAT; + DDRCFG->DFI.CFG_DFI_PHYUPD_EN.CFG_DFI_PHYUPD_EN =\ + LIBERO_SETTING_CFG_DFI_PHYUPD_EN; + DDRCFG->DFI.INIT_DFI_LP_DATA_REQ.INIT_DFI_LP_DATA_REQ =\ + LIBERO_SETTING_INIT_DFI_LP_DATA_REQ; + DDRCFG->DFI.INIT_DFI_LP_CTRL_REQ.INIT_DFI_LP_CTRL_REQ =\ + LIBERO_SETTING_INIT_DFI_LP_CTRL_REQ; + DDRCFG->DFI.INIT_DFI_LP_WAKEUP.INIT_DFI_LP_WAKEUP =\ + LIBERO_SETTING_INIT_DFI_LP_WAKEUP; + DDRCFG->DFI.INIT_DFI_DRAM_CLK_DISABLE.INIT_DFI_DRAM_CLK_DISABLE =\ + LIBERO_SETTING_INIT_DFI_DRAM_CLK_DISABLE; + DDRCFG->DFI.CFG_DFI_DATA_BYTE_DISABLE.CFG_DFI_DATA_BYTE_DISABLE =\ + LIBERO_SETTING_CFG_DFI_DATA_BYTE_DISABLE; + DDRCFG->DFI.CFG_DFI_LVL_SEL.CFG_DFI_LVL_SEL =\ + LIBERO_SETTING_CFG_DFI_LVL_SEL; + DDRCFG->DFI.CFG_DFI_LVL_PERIODIC.CFG_DFI_LVL_PERIODIC =\ + LIBERO_SETTING_CFG_DFI_LVL_PERIODIC; + DDRCFG->DFI.CFG_DFI_LVL_PATTERN.CFG_DFI_LVL_PATTERN =\ + LIBERO_SETTING_CFG_DFI_LVL_PATTERN; + DDRCFG->DFI.PHY_DFI_INIT_START.PHY_DFI_INIT_START =\ + LIBERO_SETTING_PHY_DFI_INIT_START; + DDRCFG->AXI_IF.CFG_AXI_START_ADDRESS_AXI1_0.CFG_AXI_START_ADDRESS_AXI1_0 =\ + LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI1_0; + DDRCFG->AXI_IF.CFG_AXI_START_ADDRESS_AXI1_1.CFG_AXI_START_ADDRESS_AXI1_1 =\ + LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI1_1; + DDRCFG->AXI_IF.CFG_AXI_START_ADDRESS_AXI2_0.CFG_AXI_START_ADDRESS_AXI2_0 =\ + LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI2_0; + DDRCFG->AXI_IF.CFG_AXI_START_ADDRESS_AXI2_1.CFG_AXI_START_ADDRESS_AXI2_1 =\ + LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI2_1; + DDRCFG->AXI_IF.CFG_AXI_END_ADDRESS_AXI1_0.CFG_AXI_END_ADDRESS_AXI1_0 =\ + LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI1_0; + DDRCFG->AXI_IF.CFG_AXI_END_ADDRESS_AXI1_1.CFG_AXI_END_ADDRESS_AXI1_1 =\ + LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI1_1; + DDRCFG->AXI_IF.CFG_AXI_END_ADDRESS_AXI2_0.CFG_AXI_END_ADDRESS_AXI2_0 =\ + LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI2_0; + DDRCFG->AXI_IF.CFG_AXI_END_ADDRESS_AXI2_1.CFG_AXI_END_ADDRESS_AXI2_1 =\ + LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI2_1; + DDRCFG->AXI_IF.CFG_MEM_START_ADDRESS_AXI1_0.CFG_MEM_START_ADDRESS_AXI1_0 =\ + LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI1_0; + DDRCFG->AXI_IF.CFG_MEM_START_ADDRESS_AXI1_1.CFG_MEM_START_ADDRESS_AXI1_1 =\ + LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI1_1; + DDRCFG->AXI_IF.CFG_MEM_START_ADDRESS_AXI2_0.CFG_MEM_START_ADDRESS_AXI2_0 =\ + LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI2_0; + DDRCFG->AXI_IF.CFG_MEM_START_ADDRESS_AXI2_1.CFG_MEM_START_ADDRESS_AXI2_1 =\ + LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI2_1; + DDRCFG->AXI_IF.CFG_ENABLE_BUS_HOLD_AXI1.CFG_ENABLE_BUS_HOLD_AXI1 =\ + LIBERO_SETTING_CFG_ENABLE_BUS_HOLD_AXI1; + DDRCFG->AXI_IF.CFG_ENABLE_BUS_HOLD_AXI2.CFG_ENABLE_BUS_HOLD_AXI2 =\ + LIBERO_SETTING_CFG_ENABLE_BUS_HOLD_AXI2; + DDRCFG->AXI_IF.CFG_AXI_AUTO_PCH.CFG_AXI_AUTO_PCH =\ + LIBERO_SETTING_CFG_AXI_AUTO_PCH; + DDRCFG->csr_custom.PHY_RESET_CONTROL.PHY_RESET_CONTROL =\ + LIBERO_SETTING_PHY_RESET_CONTROL; + DDRCFG->csr_custom.PHY_RESET_CONTROL.PHY_RESET_CONTROL =\ + (LIBERO_SETTING_PHY_RESET_CONTROL & ~0x8000UL); + DDRCFG->csr_custom.PHY_PC_RANK.PHY_PC_RANK = LIBERO_SETTING_PHY_PC_RANK; + DDRCFG->csr_custom.PHY_RANKS_TO_TRAIN.PHY_RANKS_TO_TRAIN =\ + LIBERO_SETTING_PHY_RANKS_TO_TRAIN; + DDRCFG->csr_custom.PHY_WRITE_REQUEST.PHY_WRITE_REQUEST =\ + LIBERO_SETTING_PHY_WRITE_REQUEST; + DDRCFG->csr_custom.PHY_READ_REQUEST.PHY_READ_REQUEST =\ + LIBERO_SETTING_PHY_READ_REQUEST; + DDRCFG->csr_custom.PHY_WRITE_LEVEL_DELAY.PHY_WRITE_LEVEL_DELAY =\ + LIBERO_SETTING_PHY_WRITE_LEVEL_DELAY; + DDRCFG->csr_custom.PHY_GATE_TRAIN_DELAY.PHY_GATE_TRAIN_DELAY =\ + LIBERO_SETTING_PHY_GATE_TRAIN_DELAY; + DDRCFG->csr_custom.PHY_EYE_TRAIN_DELAY.PHY_EYE_TRAIN_DELAY =\ + LIBERO_SETTING_PHY_EYE_TRAIN_DELAY; + DDRCFG->csr_custom.PHY_EYE_PAT.PHY_EYE_PAT = LIBERO_SETTING_PHY_EYE_PAT; + DDRCFG->csr_custom.PHY_START_RECAL.PHY_START_RECAL =\ + LIBERO_SETTING_PHY_START_RECAL; + DDRCFG->csr_custom.PHY_CLR_DFI_LVL_PERIODIC.PHY_CLR_DFI_LVL_PERIODIC =\ + LIBERO_SETTING_PHY_CLR_DFI_LVL_PERIODIC; + DDRCFG->csr_custom.PHY_TRAIN_STEP_ENABLE.PHY_TRAIN_STEP_ENABLE =\ + LIBERO_SETTING_PHY_TRAIN_STEP_ENABLE; + DDRCFG->csr_custom.PHY_LPDDR_DQ_CAL_PAT.PHY_LPDDR_DQ_CAL_PAT =\ + LIBERO_SETTING_PHY_LPDDR_DQ_CAL_PAT; + DDRCFG->csr_custom.PHY_INDPNDT_TRAINING.PHY_INDPNDT_TRAINING =\ + LIBERO_SETTING_PHY_INDPNDT_TRAINING; + DDRCFG->csr_custom.PHY_ENCODED_QUAD_CS.PHY_ENCODED_QUAD_CS =\ + LIBERO_SETTING_PHY_ENCODED_QUAD_CS; + DDRCFG->csr_custom.PHY_HALF_CLK_DLY_ENABLE.PHY_HALF_CLK_DLY_ENABLE =\ + LIBERO_SETTING_PHY_HALF_CLK_DLY_ENABLE; + +} + + +/** + * setup_ddr_segments(void) + * setup segment registers- translated DDR address as user requires + */ +void setup_ddr_segments(SEG_SETUP option) +{ + if(option == DEFAULT_SEG_SETUP) + { + SEG[0].u[0].raw = (INIT_SETTING_SEG0_0 & 0x7FFFUL); + SEG[0].u[1].raw = (INIT_SETTING_SEG0_1 & 0x7FFFUL); + SEG[1].u[2].raw = (INIT_SETTING_SEG1_2 & 0x7FFFUL); + SEG[1].u[3].raw = (INIT_SETTING_SEG1_3 & 0x7FFFUL); + SEG[1].u[4].raw = (INIT_SETTING_SEG1_4 & 0x7FFFUL); + SEG[1].u[5].raw = (INIT_SETTING_SEG1_5 & 0x7FFFUL); + } + else + { + SEG[0].u[0].raw = (LIBERO_SETTING_SEG0_0 & 0x7FFFUL); + SEG[0].u[1].raw = (LIBERO_SETTING_SEG0_1 & 0x7FFFUL); + SEG[1].u[2].raw = (LIBERO_SETTING_SEG1_2 & 0x7FFFUL); + SEG[1].u[3].raw = (LIBERO_SETTING_SEG1_3 & 0x7FFFUL); + SEG[1].u[4].raw = (LIBERO_SETTING_SEG1_4 & 0x7FFFUL); + SEG[1].u[5].raw = (LIBERO_SETTING_SEG1_5 & 0x7FFFUL); + } + /* + * disable ddr blocker + * Is cleared at reset. When written to '1' disables the blocker function + * allowing the L2 cache controller to access the DDRC. Once written to '1' + * the register cannot be written to 0, only an MSS reset will clear the + * register + */ + SEG[0].u[7].raw = 0x01U; +} + +/** + * use_software_bclk_sclk_training() + * @param ddr_type + * @return returns 1U if required, otherwise 0U + */ +static uint8_t use_software_bclk_sclk_training(DDR_TYPE ddr_type) +{ + uint8_t result = 0U; + switch (ddr_type) + { + default: + case DDR_OFF_MODE: + break; + case DDR3L: + result = 1U; + break; + case DDR3: + result = 1U; + break; + case DDR4: + result = 1U; + break; + case LPDDR3: + result = 1U; + break; + case LPDDR4: + result = 1U; + break; + } + return(result); +} + +/** + * config_ddr_io_pull_up_downs_rpc_bits() + * + * This function overrides the RPC bits related to weak pull up and + * weak pull downs. It also sets the override bit if the I/O is disabled. + * The settings come fro m Libero + * + * Note: If LIBERO_SETTING_RPC_EN_ADDCMD0_OVRT9 is not present, indicates older + * Libero core (pre 2.0.109) + * Post 2.0.109 version of Libero MSS core, weak pull up and pull down + * settings come from Libero, along with setting unused MSS DDR I/O to + * override. + * + */ +static void config_ddr_io_pull_up_downs_rpc_bits(DDR_TYPE ddr_type) +{ + if(ddr_type == LPDDR4) /* we will add other variants here once verified */ + { +#ifdef LIBERO_SETTING_RPC_EN_ADDCMD0_OVRT9 + /* set over-rides (associated bit set to 1 if I/O not being used */ + CFG_DDR_SGMII_PHY->ovrt9.ovrt9 = LIBERO_SETTING_RPC_EN_ADDCMD0_OVRT9; + CFG_DDR_SGMII_PHY->ovrt10.ovrt10 = LIBERO_SETTING_RPC_EN_ADDCMD1_OVRT10; + CFG_DDR_SGMII_PHY->ovrt11.ovrt11 = LIBERO_SETTING_RPC_EN_ADDCMD2_OVRT11; + CFG_DDR_SGMII_PHY->ovrt12.ovrt12 = LIBERO_SETTING_RPC_EN_DATA0_OVRT12; + CFG_DDR_SGMII_PHY->ovrt13.ovrt13 = LIBERO_SETTING_RPC_EN_DATA1_OVRT13; + CFG_DDR_SGMII_PHY->ovrt14.ovrt14 = LIBERO_SETTING_RPC_EN_DATA2_OVRT14; + CFG_DDR_SGMII_PHY->ovrt15.ovrt15 = LIBERO_SETTING_RPC_EN_DATA3_OVRT15; + CFG_DDR_SGMII_PHY->ovrt16.ovrt16 = LIBERO_SETTING_RPC_EN_ECC_OVRT16; + /* set the required wpu state- note: associated I/O bit 1=> off, 0=> on */ + CFG_DDR_SGMII_PHY->rpc235.rpc235 = LIBERO_SETTING_RPC235_WPD_ADD_CMD0; + CFG_DDR_SGMII_PHY->rpc236.rpc236 = LIBERO_SETTING_RPC236_WPD_ADD_CMD1; + CFG_DDR_SGMII_PHY->rpc237.rpc237 = LIBERO_SETTING_RPC237_WPD_ADD_CMD2; + CFG_DDR_SGMII_PHY->rpc238.rpc238 = LIBERO_SETTING_RPC238_WPD_DATA0; + CFG_DDR_SGMII_PHY->rpc239.rpc239 = LIBERO_SETTING_RPC239_WPD_DATA1; + CFG_DDR_SGMII_PHY->rpc240.rpc240 = LIBERO_SETTING_RPC240_WPD_DATA2; + CFG_DDR_SGMII_PHY->rpc241.rpc241 = LIBERO_SETTING_RPC241_WPD_DATA3; + CFG_DDR_SGMII_PHY->rpc242.rpc242 = LIBERO_SETTING_RPC242_WPD_ECC; + /* set the required wpd state- note: associated I/O bit 1=> off, 0=> on */ + CFG_DDR_SGMII_PHY->rpc243.rpc243 = LIBERO_SETTING_RPC243_WPU_ADD_CMD0; + CFG_DDR_SGMII_PHY->rpc244.rpc244 = LIBERO_SETTING_RPC244_WPU_ADD_CMD1; + CFG_DDR_SGMII_PHY->rpc245.rpc245 = LIBERO_SETTING_RPC245_WPU_ADD_CMD2; + CFG_DDR_SGMII_PHY->rpc246.rpc246 = LIBERO_SETTING_RPC246_WPU_DATA0; + CFG_DDR_SGMII_PHY->rpc247.rpc247 = LIBERO_SETTING_RPC247_WPU_DATA1; + CFG_DDR_SGMII_PHY->rpc248.rpc248 = LIBERO_SETTING_RPC248_WPU_DATA2; + CFG_DDR_SGMII_PHY->rpc249.rpc249 = LIBERO_SETTING_RPC249_WPU_DATA3; + CFG_DDR_SGMII_PHY->rpc250.rpc250 = LIBERO_SETTING_RPC250_WPU_ECC; +#endif + } +} + + +/** + * get the best sweep value + * @param good_index + * @return + */ +#ifdef SWEEP_ENABLED +static uint8_t get_best_sweep(sweep_index *good_index) +{ +#ifdef EXTRACT_SWEEP_RESULT + uint8_t cmd_index; + uint8_t bclk_sclk_index; + uint8_t dpc_vgen_index; + uint8_t dpc_vgen_h_index; + uint8_t dpc_vgen_vs_index; + uint8_t good_in_row; + + for (dpc_vgen_vs_index=0U; dpc_vgen_vs_index < MAX_NUMBER_DPC_VS_GEN_SWEEPS; dpc_vgen_vs_index++) + { + for (dpc_vgen_h_index=0U; dpc_vgen_h_index < MAX_NUMBER_DPC_H_GEN_SWEEPS; dpc_vgen_h_index++) + { + for (dpc_vgen_index=0U; dpc_vgen_index < MAX_NUMBER_DPC_V_GEN_SWEEPS; dpc_vgen_index++) + { + for (bclk_sclk_index=0U; bclk_sclk_index < MAX_NUMBER__BCLK_SCLK_OFFSET_SWEEPS; bclk_sclk_index++) + { + good_in_row = 0U; + for (cmd_index=0U; cmd_index < MAX_NUMBER_ADDR_CMD_OFFSET_SWEEPS; cmd_index++) + { + if (sweep_results[dpc_vgen_vs_index][dpc_vgen_h_index][dpc_vgen_index][bclk_sclk_index][cmd_index]\ + == CALIBRATION_PASSED) + { + good_in_row++; + /* + * look for 3 in a row,in x and y direction and pick the + * middle one + * */ + if((good_in_row > 2U)&&(bclk_sclk_index>1)&&(bclk_sclk_index<MAX_NUMBER__BCLK_SCLK_OFFSET_SWEEPS-1)) + { + if ((sweep_results[dpc_vgen_vs_index]\ + [dpc_vgen_h_index][dpc_vgen_index]\ + [bclk_sclk_index-1][cmd_index]\ + == CALIBRATION_PASSED)&&\ + (sweep_results[dpc_vgen_vs_index]\ + [dpc_vgen_h_index]\ + [dpc_vgen_index]\ + [bclk_sclk_index+1][cmd_index]\ + == CALIBRATION_PASSED)) + { + good_index->dpc_vgen_vs_index = dpc_vgen_vs_index; + good_index->dpc_vgen_h_index = dpc_vgen_h_index; + good_index->bclk_sclk_index = bclk_sclk_index; + good_index->dpc_vgen_index = dpc_vgen_index; + good_index->cmd_index = cmd_index - 1U; + return(0U); + } + } + } + else + { + good_in_row = 0U; + } + } + } + } + } + } + return(1U); +#else /* EXTRACT_SWEEP_RESULT */ + good_index->dpc_vgen_vs_index = 0U; + good_index->dpc_vgen_h_index = 0U; + good_index->bclk_sclk_index = 0U; + good_index->dpc_vgen_index = 0U; + good_index->cmd_index = 0U; + return(0U); +#endif +} +#endif /* SWEEP_ENABLED */ + + +#ifdef DDR_DIAGNOSTICS /* todo: add support for diagnostics below during board bring-up */ + +/*-------------------------------------------------------------------------*//** + The MSS_DDR_status() function is used to return status information to the + user. + + TODO: Define number of request inputs + + @param option + This option chooses status data we wish returned + + @param return_data + Returned data here. This must be within a defined range. + todo:Detail on the sharing of data will be system dependent. + AMP/SMU detail to be finalized at time of writing + + @return + Returns 0 on success. + TODO: Define error codes. + + Example: + The call to MSS_DDR_status(DDR_TYPE, return_data) will return 0 if + successful and the DDR type in the first four bytes of the ret_mem area. + @code + MSS_DDR_status( DDR_TYPE, ret_mem ); + @endcode + */ +uint8_t +MSS_DDR_status +( + uint8_t option, uint32_t *return_data +) +{ + uint8_t error = 0U; + + switch (option) + { + case USR_OPTION_tip_register_dump: + /* todo: WIP + * add commands here */ + break; + + default: + + break; + } + + return error; +} + + +/*-------------------------------------------------------------------------*//** + * MSS_DDR_user_commands commands from the user + * + * @param command + * User command + * @param extra_command_data + * extra data from user for particular command + * @param return_data + * data returned via supplied pointer + * @return + * status 0 => success + * + * Example: + The call to + MSS_DDR_user_commands(USR_CMD_INC_DELAY_LINE, 0x01 , return_data) + will return 0 id successful and the + DDR type in the first four bytes of the ret_mem area. + @code + MSS_DDR_user_commands(USR_CMD_INC_DELAY_LINE, 0x01 , return_data); + @endcode + */ +uint8_t +MSS_DDR_user_commands +( + uint8_t command, uint32_t *extra_command_data, uint32_t *return_data, \ + uint32_t return_size +) +{ + uint8_t error = 0U; + uint32_t *reg_address; + + switch (command) + { + case USR_CMD_GET_DDR_STATUS: + break; + case USR_CMD_GET_MODE_SETTING: + break; + case USR_CMD_GET_W_CALIBRATION: + config_copy(return_data, &calib_data, sizeof(calib_data)); + break; + case USR_CMD_GET_GREEN_ZONE: + /* READ DQ WINDOW MEASUREMENT */ + /* READ DQS WINDOW MEASUREMENT */ + /* READ VREF WINDOW MAX MEASUREMENT */ + + break; + + case USR_CMD_GET_REG: + /* + * First check if address valid + */ + config_copy(reg_address, extra_command_data, 4U); + reg_address = (uint32_t *)((uint32_t)reg_address &\ + (uint32_t)(0xFFFFFFFCUL)); + if ((reg_address >=\ + &CFG_DDR_SGMII_PHY->SOFT_RESET_DDR_PHY.SOFT_RESET_DDR_PHY)\ + && (reg_address < &CFG_DDR_SGMII_PHY->SPARE_STAT.SPARE_STAT)) + { + config_copy(return_data, reg_address, sizeof(uint32_t)); + } + else + { + error = 1U; + } + break; + + /* + * And set commands + */ + case USR_CMD_SET_GREEN_ZONE_DQ: + /* READ DQ WINDOW MEASUREMENT */ + /* + * This procedure is uses reads/writes & DQ delayline controls, to + * measure the maximum DQ offset before failure. + */ + break; + case USR_CMD_SET_GREEN_ZONE_DQS: + /* READ DQS WINDOW MEASUREMENT */ + /* + * This procedure is uses reads/writes & DQS delayline controls, to + * measure the maximum DQS offset before failure. + */ + break; + case USR_CMD_SET_GREEN_ZONE_VREF_MAX: + /* READ VREF WINDOW MAX MEASUREMENT */ + /* + * This procedure is uses reads/writes & VREF controller delayline + * controls, to measure the max VREF level. + */ + break; + case USR_CMD_SET_GREEN_ZONE_VREF_MIN: + /* READ VREF WINDOW MIN MEASUREMENT */ + /* + * This procedure is uses reads/writes & VREF controller delayline + * controls, to measure the minimum VREF level. + */ + break; + case USR_CMD_SET_RETRAIN: + /* Incremental, In-System Retraining Procedures */ + /* + * This procedure adjusts the read window to re-center clock and + * data. + * It should be triggered when the DLL code value passes a certain + * threshold, during a refresh cycle. + * Added here to allow the user to trigger. + */ + break; + case USR_CMD_SET_REG: + break; + + default: + error = 1U; + break; + } + return error; +} +#endif + +#ifdef DEBUG_DDR_INIT +#ifdef DEBUG_DDR_DDRCFG +void debug_read_ddrcfg(void) +{ + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->ADDR_MAP,\ + (sizeof(DDRCFG->ADDR_MAP)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->MC_BASE3,\ + (sizeof(DDRCFG->MC_BASE3)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->MC_BASE1,\ + (sizeof(DDRCFG->MC_BASE1)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->MC_BASE2,\ + (sizeof(DDRCFG->MC_BASE2)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->MPFE,\ + (sizeof(DDRCFG->MPFE)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->REORDER,\ + (sizeof(DDRCFG->REORDER)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->RMW,\ + (sizeof(DDRCFG->RMW)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->ECC,\ + (sizeof(DDRCFG->ECC)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->READ_CAPT,\ + (sizeof(DDRCFG->READ_CAPT)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->MTA,\ + (sizeof(DDRCFG->MTA)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->DYN_WIDTH_ADJ,\ + (sizeof(DDRCFG->DYN_WIDTH_ADJ)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->CA_PAR_ERR,\ + (sizeof(DDRCFG->CA_PAR_ERR)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->DFI,\ + (sizeof(DDRCFG->DFI)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->AXI_IF,\ + (sizeof(DDRCFG->AXI_IF)/4U)); + (void)print_reg_array(g_debug_uart , + (uint32_t *)&DDRCFG->csr_custom,\ + (sizeof(DDRCFG->csr_custom)/4U)); + return; +} +#endif +#endif + + +const uint8_t REFCLK_OFFSETS[][5U] = { + {LIBERO_SETTING_REFCLK_DDR3_1600_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_DDR3_1600_OFFSET_0, + LIBERO_SETTING_REFCLK_DDR3_1600_OFFSET_1, + LIBERO_SETTING_REFCLK_DDR3_1600_OFFSET_2, + LIBERO_SETTING_REFCLK_DDR3_1600_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_DDR3L_1600_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_DDR3L_1600_OFFSET_0, + LIBERO_SETTING_REFCLK_DDR3L_1600_OFFSET_1, + LIBERO_SETTING_REFCLK_DDR3L_1600_OFFSET_2, + LIBERO_SETTING_REFCLK_DDR3_1600_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_DDR4_1600_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_0, + LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_1, + LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_2, + LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_LPDDR3_1600_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_0, + LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_1, + LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_2, + LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_LPDDR4_1600_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_0, + LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_1, + LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_2, + LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_3}, + + {LIBERO_SETTING_REFCLK_DDR3_1333_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_0, + LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_1, + LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_2, + LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_DDR3L_1333_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_DDR3L_1333_OFFSET_0, + LIBERO_SETTING_REFCLK_DDR3L_1333_OFFSET_1, + LIBERO_SETTING_REFCLK_DDR3L_1333_OFFSET_2, + LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_DDR4_1333_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_0, + LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_1, + LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_2, + LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_LPDDR3_1333_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_0, + LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_1, + LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_2, + LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_3}, + { + LIBERO_SETTING_REFCLK_LPDDR4_1333_NUM_OFFSETS, + LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_0, + LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_1, + LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_2, + LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_3}, +}; + +/** + * ddr_manual_addcmd_refclk_offset This function determines current + * sweep offset based on DDR type + * @param ddr_type + * @param refclk_sweep_index + * @return + */ +#ifdef MANUAL_ADDCMD_TRAINIG +static uint8_t ddr_manual_addcmd_refclk_offset(DDR_TYPE ddr_type, uint8_t * refclk_sweep_index) +{ + uint8_t refclk_offset; + uint8_t type_array_index; + + type_array_index = (uint8_t)ddr_type; + if(LIBERO_SETTING_DDR_CLK == DDR_1333_MHZ) + { + type_array_index = type_array_index + (uint8_t)LPDDR4; + } + + if (*refclk_sweep_index >= REFCLK_OFFSETS[type_array_index][0U]) + { + *refclk_sweep_index = 0U; + } + + refclk_offset = REFCLK_OFFSETS[type_array_index][*refclk_sweep_index + 1U]; + + *refclk_sweep_index = (*refclk_sweep_index + 1U); + + return refclk_offset; +} +#endif + + +#endif /* DDR_SUPPORT */ + |