// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) Marvell International Ltd. and its affiliates */ #include "ddr3_init.h" #include "mv_ddr_common.h" /* * 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_8GB }; static char *ddr_type = "DDR3"; /* * generic_init_controller controls D-unit configuration: * '1' - dynamic D-unit configuration, */ u8 generic_init_controller = 1; static int mv_ddr_training_params_set(u8 dev_num); /* * Name: ddr3_init - Main DDR3 Init function * Desc: This routine initialize the DDR3 MC and runs HW training. * Args: None. * Notes: * Returns: None. */ int ddr3_init(void) { struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); u32 octets_per_if_num; int status; int is_manual_cal_done; /* Print mv_ddr version */ mv_ddr_ver_print(); mv_ddr_pre_training_fixup(); /* SoC/Board special initializations */ mv_ddr_pre_training_soc_config(ddr_type); /* Set log level for training library */ mv_ddr_user_log_level_set(DEBUG_BLOCK_ALL); mv_ddr_early_init(); if (mv_ddr_topology_map_update() == NULL) { printf("mv_ddr: failed to update topology\n"); return MV_FAIL; } if (mv_ddr_early_init2() != MV_OK) return MV_FAIL; /* Set training algorithm's parameters */ status = mv_ddr_training_params_set(0); if (MV_OK != status) return status; mv_ddr_mc_config(); is_manual_cal_done = mv_ddr_manual_cal_do(); mv_ddr_mc_init(); if (!is_manual_cal_done) { } status = ddr3_silicon_post_init(); if (MV_OK != status) { printf("DDR3 Post Init - FAILED 0x%x\n", status); return status; } /* PHY initialization (Training) */ status = hws_ddr3_tip_run_alg(0, ALGO_TYPE_DYNAMIC); if (MV_OK != status) { printf("%s Training Sequence - FAILED\n", ddr_type); return status; } #if defined(CONFIG_PHY_STATIC_PRINT) mv_ddr_phy_static_print(); #endif /* Post MC/PHY initializations */ mv_ddr_post_training_soc_config(ddr_type); mv_ddr_post_training_fixup(); 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(); } printf("mv_ddr: completed successfully\n"); return MV_OK; } uint64_t mv_ddr_get_memory_size_per_cs_in_bits(void) { uint64_t memory_size_per_cs; u32 bus_cnt, num_of_active_bus = 0; u32 num_of_sub_phys_per_ddr_unit = 0; struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); u32 octets_per_if_num = ddr3_tip_dev_attr_get(DEV_NUM_0, MV_ATTR_OCTET_PER_INTERFACE); /* 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++; } /* 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; /* 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 memory_size_per_cs; } uint64_t mv_ddr_get_total_memory_size_in_bits(void) { uint64_t total_memory_size = 0; uint64_t memory_size_per_cs = 0; /* get the number of cs */ u32 max_cs = ddr3_tip_max_cs_get(DEV_NUM_0); memory_size_per_cs = mv_ddr_get_memory_size_per_cs_in_bits(); total_memory_size = (uint64_t)max_cs * memory_size_per_cs; return total_memory_size; } int ddr3_if_ecc_enabled(void) { struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) || DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask) || DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask)) return 1; else return 0; } /* * Name: mv_ddr_training_params_set * Desc: * Args: * Notes: sets internal training params * Returns: */ static int mv_ddr_training_params_set(u8 dev_num) { struct tune_train_params params; 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.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) { printf("%s Training Sequence - FAILED\n", ddr_type); return status; } return MV_OK; }