diff options
author | Chris Packham | 2018-05-10 13:28:29 +1200 |
---|---|---|
committer | Stefan Roese | 2018-05-14 10:01:56 +0200 |
commit | 2b4ffbf6b4944a0b3125fd2c9c0ba3568264367a (patch) | |
tree | dc75d0e07677505b8611a670483a349f214c9e75 /drivers/ddr/marvell/a38x/ddr3_init.c | |
parent | 00a7767766ace1f3ca3de7f9d44e145b9092bbad (diff) |
ARM: mvebu: a38x: sync ddr training code with upstream
This syncs drivers/ddr/marvell/a38x/ with the mv_ddr-armada-17.10 branch
of https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git.
The upstream code is incorporated omitting the ddr4 and apn806 and
folding the nested a38x directory up one level. After that a
semi-automated step is used to drop unused features with unifdef
find drivers/ddr/marvell/a38x/ -name '*.[ch]' | \
xargs unifdef -m -UMV_DDR -UMV_DDR_ATF -UCONFIG_DDR4 \
-UCONFIG_APN806 -UCONFIG_MC_STATIC \
-UCONFIG_MC_STATIC_PRINT -UCONFIG_PHY_STATIC \
-UCONFIG_64BIT
INTER_REGS_BASE is updated to be defined as SOC_REGS_PHY_BASE.
Some now empty files are removed and the ternary license is replaced
with a SPDX GPL-2.0+ identifier.
Signed-off-by: Chris Packham <judge.packham@gmail.com>
Signed-off-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'drivers/ddr/marvell/a38x/ddr3_init.c')
-rw-r--r-- | drivers/ddr/marvell/a38x/ddr3_init.c | 745 |
1 files changed, 127 insertions, 618 deletions
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c index 73d984ba66a..27dbf4f44b9 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.c +++ b/drivers/ddr/marvell/a38x/ddr3_init.c @@ -3,239 +3,30 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include <common.h> -#include <i2c.h> -#include <spl.h> -#include <asm/io.h> -#include <asm/arch/cpu.h> -#include <asm/arch/soc.h> - #include "ddr3_init.h" +#include "mv_ddr_common.h" -#include "../../../../arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h" - -static struct dlb_config ddr3_dlb_config_table[] = { - {REG_STATIC_DRAM_DLB_CONTROL, 0x2000005c}, - {DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x00880000}, - {DLB_AGING_REGISTER, 0x0f7f007f}, - {DLB_EVICTION_CONTROL_REG, 0x0000129f}, - {DLB_EVICTION_TIMERS_REGISTER_REG, 0x00ff0000}, - {DLB_BUS_WEIGHTS_DIFF_CS, 0x04030802}, - {DLB_BUS_WEIGHTS_DIFF_BG, 0x00000a02}, - {DLB_BUS_WEIGHTS_SAME_BG, 0x09000a01}, - {DLB_BUS_WEIGHTS_RD_WR, 0x00020005}, - {DLB_BUS_WEIGHTS_ATTR_SYS_PRIO, 0x00060f10}, - {DLB_MAIN_QUEUE_MAP, 0x00000543}, - {DLB_LINE_SPLIT, 0x00000000}, - {DLB_USER_COMMAND_REG, 0x00000000}, - {0x0, 0x0} -}; - -static struct dlb_config ddr3_dlb_config_table_a0[] = { - {REG_STATIC_DRAM_DLB_CONTROL, 0x2000005c}, - {DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x00880000}, - {DLB_AGING_REGISTER, 0x0f7f007f}, - {DLB_EVICTION_CONTROL_REG, 0x0000129f}, - {DLB_EVICTION_TIMERS_REGISTER_REG, 0x00ff0000}, - {DLB_BUS_WEIGHTS_DIFF_CS, 0x04030802}, - {DLB_BUS_WEIGHTS_DIFF_BG, 0x00000a02}, - {DLB_BUS_WEIGHTS_SAME_BG, 0x09000a01}, - {DLB_BUS_WEIGHTS_RD_WR, 0x00020005}, - {DLB_BUS_WEIGHTS_ATTR_SYS_PRIO, 0x00060f10}, - {DLB_MAIN_QUEUE_MAP, 0x00000543}, - {DLB_LINE_SPLIT, 0x00000000}, - {DLB_USER_COMMAND_REG, 0x00000000}, - {0x0, 0x0} -}; - -#if defined(CONFIG_ARMADA_38X) -struct dram_modes { - char *mode_name; - u8 cpu_freq; - u8 fab_freq; - u8 chip_id; - u8 chip_board_rev; - struct reg_data *regs; -}; - -struct dram_modes ddr_modes[] = { -}; -#endif /* defined(CONFIG_ARMADA_38X) */ - -/* Translates topology map definitions to real memory size in bits */ +/* + * Translates topology map definitions to real memory size in bits + * (per values in ddr3_training_ip_def.h) + */ u32 mem_size[] = { - ADDR_SIZE_512MB, ADDR_SIZE_1GB, ADDR_SIZE_2GB, ADDR_SIZE_4GB, + ADDR_SIZE_512MB, + ADDR_SIZE_1GB, + ADDR_SIZE_2GB, + ADDR_SIZE_4GB, ADDR_SIZE_8GB }; static char *ddr_type = "DDR3"; /* - * Set 1 to use dynamic DUNIT configuration, - * set 0 (supported for A380 and AC3) to configure DUNIT in values set by - * ddr3_tip_init_specific_reg_config + * generic_init_controller controls D-unit configuration: + * '1' - dynamic D-unit configuration, */ u8 generic_init_controller = 1; -static int ddr3_hws_tune_training_params(u8 dev_num); - -/* device revision */ -#define DEV_VERSION_ID_REG 0x1823c -#define REVISON_ID_OFFS 8 -#define REVISON_ID_MASK 0xf00 - -/* A38x revisions */ -#define MV_88F68XX_Z1_ID 0x0 -#define MV_88F68XX_A0_ID 0x4 -/* A39x revisions */ -#define MV_88F69XX_Z1_ID 0x2 - -/* - * sys_env_dlb_config_ptr_get - * - * DESCRIPTION: defines pointer to to DLB COnfiguration table - * - * INPUT: none - * - * OUTPUT: pointer to DLB COnfiguration table - * - * RETURN: - * returns pointer to DLB COnfiguration table - */ -struct dlb_config *sys_env_dlb_config_ptr_get(void) -{ -#ifdef CONFIG_ARMADA_39X - return &ddr3_dlb_config_table_a0[0]; -#else - if (sys_env_device_rev_get() == MV_88F68XX_A0_ID) - return &ddr3_dlb_config_table_a0[0]; - else - return &ddr3_dlb_config_table[0]; -#endif -} - -/* - * sys_env_get_cs_ena_from_reg - * - * DESCRIPTION: Get bit mask of enabled CS - * - * INPUT: None - * - * OUTPUT: None - * - * RETURN: - * Bit mask of enabled CS, 1 if only CS0 enabled, - * 3 if both CS0 and CS1 enabled - */ -u32 sys_env_get_cs_ena_from_reg(void) -{ - return reg_read(REG_DDR3_RANK_CTRL_ADDR) & - REG_DDR3_RANK_CTRL_CS_ENA_MASK; -} - -static void ddr3_restore_and_set_final_windows(u32 *win) -{ - u32 win_ctrl_reg, num_of_win_regs; - u32 cs_ena = sys_env_get_cs_ena_from_reg(); - u32 ui; - - win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; - num_of_win_regs = 16; - - /* Return XBAR windows 4-7 or 16-19 init configuration */ - for (ui = 0; ui < num_of_win_regs; ui++) - reg_write((win_ctrl_reg + 0x4 * ui), win[ui]); - - printf("%s Training Sequence - Switching XBAR Window to FastPath Window\n", - ddr_type); - -#if defined DYNAMIC_CS_SIZE_CONFIG - if (ddr3_fast_path_dynamic_cs_size_config(cs_ena) != MV_OK) - printf("ddr3_fast_path_dynamic_cs_size_config FAILED\n"); -#else - u32 reg, cs; - reg = 0x1fffffe1; - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - reg |= (cs << 2); - break; - } - } - /* Open fast path Window to - 0.5G */ - reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, reg); -#endif -} - -static int ddr3_save_and_set_training_windows(u32 *win) -{ - u32 cs_ena; - u32 reg, tmp_count, cs, ui; - u32 win_ctrl_reg, win_base_reg, win_remap_reg; - u32 num_of_win_regs, win_jump_index; - win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; - win_base_reg = REG_XBAR_WIN_4_BASE_ADDR; - win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR; - win_jump_index = 0x10; - num_of_win_regs = 16; - struct hws_topology_map *tm = ddr3_get_topology_map(); - -#ifdef DISABLE_L2_FILTERING_DURING_DDR_TRAINING - /* - * Disable L2 filtering during DDR training - * (when Cross Bar window is open) - */ - reg_write(ADDRESS_FILTERING_END_REGISTER, 0); -#endif - - cs_ena = tm->interface_params[0].as_bus_params[0].cs_bitmask; - - /* Close XBAR Window 19 - Not needed */ - /* {0x000200e8} - Open Mbus Window - 2G */ - reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0); - - /* Save XBAR Windows 4-19 init configurations */ - for (ui = 0; ui < num_of_win_regs; ui++) - win[ui] = reg_read(win_ctrl_reg + 0x4 * ui); - - /* Open XBAR Windows 4-7 or 16-19 for other CS */ - reg = 0; - tmp_count = 0; - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - switch (cs) { - case 0: - reg = 0x0e00; - break; - case 1: - reg = 0x0d00; - break; - case 2: - reg = 0x0b00; - break; - case 3: - reg = 0x0700; - break; - } - reg |= (1 << 0); - reg |= (SDRAM_CS_SIZE & 0xffff0000); - - reg_write(win_ctrl_reg + win_jump_index * tmp_count, - reg); - reg = (((SDRAM_CS_SIZE + 1) * (tmp_count)) & - 0xffff0000); - reg_write(win_base_reg + win_jump_index * tmp_count, - reg); - - if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR) - reg_write(win_remap_reg + - win_jump_index * tmp_count, 0); - - tmp_count++; - } - } - - return MV_OK; -} +static int mv_ddr_training_params_set(u8 dev_num); /* * Name: ddr3_init - Main DDR3 Init function @@ -246,464 +37,182 @@ static int ddr3_save_and_set_training_windows(u32 *win) */ int ddr3_init(void) { - u32 reg = 0; - u32 soc_num; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 octets_per_if_num; int status; - u32 win[16]; - - /* SoC/Board special Initializtions */ - /* Get version from internal library */ - ddr3_print_version(); - - /*Add sub_version string */ - DEBUG_INIT_C("", SUB_VERSION, 1); - - /* Switching CPU to MRVL ID */ - soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >> - SAR1_CPU_CORE_OFFSET; - switch (soc_num) { - case 0x3: - case 0x1: - reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET); - case 0x0: - reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET); - default: - break; - } + int is_manual_cal_done; - /* - * Set DRAM Reset Mask in case detected GPIO indication of wakeup from - * suspend i.e the DRAM values will not be overwritten / reset when - * waking from suspend - */ - if (sys_env_suspend_wakeup_check() == - SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED) { - reg_bit_set(REG_SDRAM_INIT_CTRL_ADDR, - 1 << REG_SDRAM_INIT_RESET_MASK_OFFS); - } + /* Print mv_ddr version */ + mv_ddr_ver_print(); - /* - * Stage 0 - Set board configuration - */ + mv_ddr_pre_training_fixup(); - /* Check if DRAM is already initialized */ - if (reg_read(REG_BOOTROM_ROUTINE_ADDR) & - (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { - printf("%s Training Sequence - 2nd boot - Skip\n", ddr_type); - return MV_OK; - } + /* SoC/Board special initializations */ + mv_ddr_pre_training_soc_config(ddr_type); - /* - * Stage 1 - Dunit Setup - */ - - /* Fix read ready phases for all SOC in reg 0x15c8 */ - reg = reg_read(REG_TRAINING_DEBUG_3_ADDR); - reg &= ~(REG_TRAINING_DEBUG_3_MASK); - reg |= 0x4; /* Phase 0 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << REG_TRAINING_DEBUG_3_OFFS); - reg |= (0x4 << (1 * REG_TRAINING_DEBUG_3_OFFS)); /* Phase 1 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (3 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (3 * REG_TRAINING_DEBUG_3_OFFS)); /* Phase 3 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (4 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (4 * REG_TRAINING_DEBUG_3_OFFS)); - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (5 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (5 * REG_TRAINING_DEBUG_3_OFFS)); - reg_write(REG_TRAINING_DEBUG_3_ADDR, reg); - - /* - * Axi_bresp_mode[8] = Compliant, - * Axi_addr_decode_cntrl[11] = Internal, - * Axi_data_bus_width[0] = 128bit - * */ - /* 0x14a8 - AXI Control Register */ - reg_write(REG_DRAM_AXI_CTRL_ADDR, 0); - - /* - * Stage 2 - Training Values Setup - */ - /* Set X-BAR windows for the training sequence */ - ddr3_save_and_set_training_windows(win); - - - /* Tune training algo paramteres */ - status = ddr3_hws_tune_training_params(0); - if (MV_OK != status) - return status; + /* Set log level for training library */ + mv_ddr_user_log_level_set(DEBUG_BLOCK_ALL); - /* Set log level for training lib */ - ddr3_hws_set_log_level(DEBUG_BLOCK_ALL, DEBUG_LEVEL_ERROR); + mv_ddr_early_init(); - /* Start New Training IP */ - status = ddr3_hws_hw_training(); - if (MV_OK != status) { - printf("%s Training Sequence - FAILED\n", ddr_type); - return status; + if (mv_ddr_topology_map_update() == NULL) { + printf("mv_ddr: failed to update topology\n"); + return MV_FAIL; } - /* - * Stage 3 - Finish - */ - /* Restore and set windows */ - ddr3_restore_and_set_final_windows(win); - - /* Update DRAM init indication in bootROM register */ - reg = reg_read(REG_BOOTROM_ROUTINE_ADDR); - reg_write(REG_BOOTROM_ROUTINE_ADDR, - reg | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)); + if (mv_ddr_early_init2() != MV_OK) + return MV_FAIL; - /* DLB config */ - ddr3_new_tip_dlb_config(); + /* Set training algorithm's parameters */ + status = mv_ddr_training_params_set(0); + if (MV_OK != status) + return status; -#if defined(ECC_SUPPORT) - if (ddr3_if_ecc_enabled()) - ddr3_new_tip_ecc_scrub(); -#endif - printf("%s Training Sequence - Ended Successfully\n", ddr_type); + mv_ddr_mc_config(); - return MV_OK; -} + is_manual_cal_done = mv_ddr_manual_cal_do(); -/* - * Name: ddr3_get_cpu_freq - * Desc: read S@R and return CPU frequency - * Args: - * Notes: - * Returns: required value - */ -u32 ddr3_get_cpu_freq(void) -{ - return ddr3_tip_get_init_freq(); -} + mv_ddr_mc_init(); -/* - * Name: ddr3_get_fab_opt - * Desc: read S@R and return CPU frequency - * Args: - * Notes: - * Returns: required value - */ -u32 ddr3_get_fab_opt(void) -{ - return 0; /* No fabric */ -} - -/* - * Name: ddr3_get_static_m_cValue - Init Memory controller with - * static parameters - * Desc: Use this routine to init the controller without the HW training - * procedure. - * User must provide compatible header file with registers data. - * Args: None. - * Notes: - * Returns: None. - */ -u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, - u32 offset2, u32 mask2) -{ - u32 reg, temp; - - reg = reg_read(reg_addr); - - temp = (reg >> offset1) & mask1; - if (mask2) - temp |= (reg >> offset2) & mask2; + if (!is_manual_cal_done) { + } - return temp; -} -/* - * Name: ddr3_get_static_ddr_mode - Init Memory controller with - * static parameters - * Desc: Use this routine to init the controller without the HW training - * procedure. - * User must provide compatible header file with registers data. - * Args: None. - * Notes: - * Returns: None. - */ -u32 ddr3_get_static_ddr_mode(void) -{ - u32 chip_board_rev, i; - u32 size; - - /* Valid only for A380 only, MSYS using dynamic controller config */ -#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT - /* - * Customer boards select DDR mode according to - * board ID & Sample@Reset - */ - chip_board_rev = mv_board_id_get(); -#else - /* Marvell boards select DDR mode according to Sample@Reset only */ - chip_board_rev = MARVELL_BOARD; -#endif - - size = ARRAY_SIZE(ddr_modes); - for (i = 0; i < size; i++) { - if ((ddr3_get_cpu_freq() == ddr_modes[i].cpu_freq) && - (ddr3_get_fab_opt() == ddr_modes[i].fab_freq) && - (chip_board_rev == ddr_modes[i].chip_board_rev)) - return i; + status = ddr3_silicon_post_init(); + if (MV_OK != status) { + printf("DDR3 Post Init - FAILED 0x%x\n", status); + return status; } - DEBUG_INIT_S("\n*** Error: ddr3_get_static_ddr_mode: No match for requested DDR mode. ***\n\n"); - - return 0; -} + /* PHY initialization (Training) */ + status = hws_ddr3_tip_run_alg(0, ALGO_TYPE_DYNAMIC); + if (MV_OK != status) { + printf("%s Training Sequence - FAILED\n", ddr_type); + return status; + } -/****************************************************************************** - * Name: ddr3_get_cs_num_from_reg - * Desc: - * Args: - * Notes: - * Returns: - */ -u32 ddr3_get_cs_num_from_reg(void) -{ - u32 cs_ena = sys_env_get_cs_ena_from_reg(); - u32 cs_count = 0; - u32 cs; +#if defined(CONFIG_PHY_STATIC_PRINT) + mv_ddr_phy_static_print(); +#endif - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) - cs_count++; - } + /* Post MC/PHY initializations */ + mv_ddr_post_training_soc_config(ddr_type); - return cs_count; -} + mv_ddr_post_training_fixup(); -void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps) -{ - u32 tmp, hclk = 200; - - switch (freq_mode) { - case 4: - tmp = 1; /* DDR_400; */ - hclk = 200; - break; - case 0x8: - tmp = 1; /* DDR_666; */ - hclk = 333; - break; - case 0xc: - tmp = 1; /* DDR_800; */ - hclk = 400; - break; - default: - *ddr_freq = 0; - *hclk_ps = 0; - break; + octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + if (ddr3_if_ecc_enabled()) { + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) || + MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(tm->bus_act_mask, octets_per_if_num)) + mv_ddr_mem_scrubbing(); + else + ddr3_new_tip_ecc_scrub(); } - *ddr_freq = tmp; /* DDR freq define */ - *hclk_ps = 1000000 / hclk; /* values are 1/HCLK in ps */ + printf("mv_ddr: completed successfully\n"); - return; + return MV_OK; } -void ddr3_new_tip_dlb_config(void) +uint64_t mv_ddr_get_memory_size_per_cs_in_bits(void) { - u32 reg, i = 0; - struct dlb_config *config_table_ptr = sys_env_dlb_config_ptr_get(); - - /* Write the configuration */ - while (config_table_ptr[i].reg_addr != 0) { - reg_write(config_table_ptr[i].reg_addr, - config_table_ptr[i].reg_data); - i++; - } + uint64_t memory_size_per_cs; - /* Enable DLB */ - reg = reg_read(REG_STATIC_DRAM_DLB_CONTROL); - reg |= DLB_ENABLE | DLB_WRITE_COALESING | DLB_AXI_PREFETCH_EN | - DLB_MBUS_PREFETCH_EN | PREFETCH_N_LN_SZ_TR; - reg_write(REG_STATIC_DRAM_DLB_CONTROL, reg); -} + u32 bus_cnt, num_of_active_bus = 0; + u32 num_of_sub_phys_per_ddr_unit = 0; -int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena) -{ - u32 reg, cs; - u32 mem_total_size = 0; - u32 cs_mem_size = 0; - u32 mem_total_size_c, cs_mem_size_c; - -#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - u32 physical_mem_size; - u32 max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE; - struct hws_topology_map *tm = ddr3_get_topology_map(); -#endif + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - /* Open fast path windows */ - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - /* get CS size */ - if (ddr3_calc_mem_cs_size(cs, &cs_mem_size) != MV_OK) - return MV_FAIL; - -#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - /* - * if number of address pins doesn't allow to use max - * mem size that is defined in topology - * mem size is defined by DEVICE_MAX_DRAM_ADDRESS_SIZE - */ - physical_mem_size = mem_size - [tm->interface_params[0].memory_size]; - - if (ddr3_get_device_width(cs) == 16) { - /* - * 16bit mem device can be twice more - no need - * in less significant pin - */ - max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE * 2; - } - - if (physical_mem_size > max_mem_size) { - cs_mem_size = max_mem_size * - (ddr3_get_bus_width() / - ddr3_get_device_width(cs)); - printf("Updated Physical Mem size is from 0x%x to %x\n", - physical_mem_size, - DEVICE_MAX_DRAM_ADDRESS_SIZE); - } -#endif + u32 octets_per_if_num = ddr3_tip_dev_attr_get(DEV_NUM_0, MV_ATTR_OCTET_PER_INTERFACE); - /* set fast path window control for the cs */ - reg = 0xffffe1; - reg |= (cs << 2); - reg |= (cs_mem_size - 1) & 0xffff0000; - /*Open fast path Window */ - reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg); - - /* Set fast path window base address for the cs */ - reg = ((cs_mem_size) * cs) & 0xffff0000; - /* Set base address */ - reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg); - - /* - * Since memory size may be bigger than 4G the summ may - * be more than 32 bit word, - * so to estimate the result divide mem_total_size and - * cs_mem_size by 0x10000 (it is equal to >> 16) - */ - mem_total_size_c = mem_total_size >> 16; - cs_mem_size_c = cs_mem_size >> 16; - /* if the sum less than 2 G - calculate the value */ - if (mem_total_size_c + cs_mem_size_c < 0x10000) - mem_total_size += cs_mem_size; - else /* put max possible size */ - mem_total_size = L2_FILTER_FOR_MAX_MEMORY_SIZE; - } + /* count the number of active bus */ + for (bus_cnt = 0; bus_cnt < octets_per_if_num - 1/* ignore ecc octet */; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + num_of_active_bus++; } - /* Set L2 filtering to Max Memory size */ - reg_write(ADDRESS_FILTERING_END_REGISTER, mem_total_size); - - return MV_OK; -} - -u32 ddr3_get_bus_width(void) -{ - u32 bus_width; + /* calculate number of sub-phys per ddr unit */ + if (tm->interface_params[0].bus_width/* supports only single interface */ == MV_DDR_DEV_WIDTH_16BIT) + num_of_sub_phys_per_ddr_unit = TWO_SUB_PHYS; + if (tm->interface_params[0].bus_width/* supports only single interface */ == MV_DDR_DEV_WIDTH_8BIT) + num_of_sub_phys_per_ddr_unit = SINGLE_SUB_PHY; - bus_width = (reg_read(REG_SDRAM_CONFIG_ADDR) & 0x8000) >> - REG_SDRAM_CONFIG_WIDTH_OFFS; + /* calculate dram size per cs */ + memory_size_per_cs = (uint64_t)mem_size[tm->interface_params[0].memory_size] * (uint64_t)num_of_active_bus + / (uint64_t)num_of_sub_phys_per_ddr_unit * (uint64_t)MV_DDR_NUM_BITS_IN_BYTE; - return (bus_width == 0) ? 16 : 32; + return memory_size_per_cs; } -u32 ddr3_get_device_width(u32 cs) +uint64_t mv_ddr_get_total_memory_size_in_bits(void) { - u32 device_width; + uint64_t total_memory_size = 0; + uint64_t memory_size_per_cs = 0; - device_width = (reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR) & - (0x3 << (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs))) >> - (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs); + /* get the number of cs */ + u32 max_cs = ddr3_tip_max_cs_get(DEV_NUM_0); - return (device_width == 0) ? 8 : 16; -} + memory_size_per_cs = mv_ddr_get_memory_size_per_cs_in_bits(); + total_memory_size = (uint64_t)max_cs * memory_size_per_cs; -static int ddr3_get_device_size(u32 cs) -{ - u32 device_size_low, device_size_high, device_size; - u32 data, cs_low_offset, cs_high_offset; - - cs_low_offset = REG_SDRAM_ADDRESS_SIZE_OFFS + cs * 4; - cs_high_offset = REG_SDRAM_ADDRESS_SIZE_OFFS + - REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS + cs; - - data = reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR); - device_size_low = (data >> cs_low_offset) & 0x3; - device_size_high = (data >> cs_high_offset) & 0x1; - - device_size = device_size_low | (device_size_high << 2); - - switch (device_size) { - case 0: - return 2048; - case 2: - return 512; - case 3: - return 1024; - case 4: - return 4096; - case 5: - return 8192; - case 1: - default: - DEBUG_INIT_C("Error: Wrong device size of Cs: ", cs, 1); - /* - * Small value will give wrong emem size in - * ddr3_calc_mem_cs_size - */ - return 0; - } + return total_memory_size; } -int ddr3_calc_mem_cs_size(u32 cs, u32 *cs_size) +int ddr3_if_ecc_enabled(void) { - int cs_mem_size; - - /* Calculate in GiB */ - cs_mem_size = ((ddr3_get_bus_width() / ddr3_get_device_width(cs)) * - ddr3_get_device_size(cs)) / 8; - - /* - * Multiple controller bus width, 2x for 64 bit - * (SoC controller may be 32 or 64 bit, - * so bit 15 in 0x1400, that means if whole bus used or only half, - * have a differnt meaning - */ - cs_mem_size *= DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER; - - if (!cs_mem_size || (cs_mem_size == 64) || (cs_mem_size == 4096)) { - DEBUG_INIT_C("Error: Wrong Memory size of Cs: ", cs, 1); - return MV_BAD_VALUE; - } + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - *cs_size = cs_mem_size << 20; - return MV_OK; + if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) || + DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask) || + DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask)) + return 1; + else + return 0; } /* - * Name: ddr3_hws_tune_training_params + * Name: mv_ddr_training_params_set * Desc: * Args: - * Notes: Tune internal training params + * Notes: sets internal training params * Returns: */ -static int ddr3_hws_tune_training_params(u8 dev_num) +static int mv_ddr_training_params_set(u8 dev_num) { struct tune_train_params params; int status; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 if_id; + u32 cs_num; + + CHECK_STATUS(ddr3_tip_get_first_active_if + (dev_num, tm->if_act_mask, + &if_id)); + + CHECK_STATUS(calc_cs_num(dev_num, if_id, &cs_num)); /* NOTE: do not remove any field initilization */ params.ck_delay = TUNE_TRAINING_PARAMS_CK_DELAY; - params.ck_delay_16 = TUNE_TRAINING_PARAMS_CK_DELAY_16; - params.p_finger = TUNE_TRAINING_PARAMS_PFINGER; - params.n_finger = TUNE_TRAINING_PARAMS_NFINGER; params.phy_reg3_val = TUNE_TRAINING_PARAMS_PHYREG3VAL; + params.g_zpri_data = TUNE_TRAINING_PARAMS_PRI_DATA; + params.g_znri_data = TUNE_TRAINING_PARAMS_NRI_DATA; + params.g_zpri_ctrl = TUNE_TRAINING_PARAMS_PRI_CTRL; + params.g_znri_ctrl = TUNE_TRAINING_PARAMS_NRI_CTRL; + params.g_znodt_data = TUNE_TRAINING_PARAMS_N_ODT_DATA; + params.g_zpodt_ctrl = TUNE_TRAINING_PARAMS_P_ODT_CTRL; + params.g_znodt_ctrl = TUNE_TRAINING_PARAMS_N_ODT_CTRL; + + params.g_zpodt_data = TUNE_TRAINING_PARAMS_P_ODT_DATA; + params.g_dic = TUNE_TRAINING_PARAMS_DIC; + params.g_rtt_nom = TUNE_TRAINING_PARAMS_RTT_NOM; + if (cs_num == 1) { + params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_1CS; + params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS; + } else { + params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_2CS; + params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS; + } status = ddr3_tip_tune_training_params(dev_num, ¶ms); if (MV_OK != status) { |