X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fddr%2Ffsl%2Foptions.c;h=3c09c643febd87085957a865a237f30381d5c674;hb=cbb0b7e03641bbeea558b7d0497d0267578459a2;hp=4aafcceaf5939ae16e764a8619e2bd12e2367613;hpb=f15ea6e1d67782a1626d4a4922b6c20e380085e5;p=oweals%2Fu-boot.git diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 4aafcceaf5..3c09c643fe 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -1,5 +1,5 @@ /* - * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc. + * Copyright 2008, 2010-2014 Freescale Semiconductor, Inc. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -29,7 +29,7 @@ struct dynamic_odt { unsigned int odt_rtt_wr; }; -#ifdef CONFIG_SYS_FSL_DDR3 +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) static const struct dynamic_odt single_Q[4] = { { /* cs0 */ FSL_DDR_ODT_NEVER, @@ -259,7 +259,7 @@ static const struct dynamic_odt odt_unknown[4] = { DDR3_RTT_OFF } }; -#else /* CONFIG_SYS_FSL_DDR3 */ +#else /* CONFIG_SYS_FSL_DDR3 || CONFIG_SYS_FSL_DDR4 */ static const struct dynamic_odt single_Q[4] = { {0, 0, 0, 0}, {0, 0, 0, 0}, @@ -499,7 +499,7 @@ static inline unsigned int auto_bank_intlv(dimm_params_t *pdimm) return 0; } -unsigned int populate_memctl_options(int all_dimms_registered, +unsigned int populate_memctl_options(const common_timing_params_t *common_dimm, memctl_options_t *popts, dimm_params_t *pdimm, unsigned int ctrl_num) @@ -507,7 +507,9 @@ unsigned int populate_memctl_options(int all_dimms_registered, unsigned int i; char buffer[HWCONFIG_BUFFER_SIZE]; char *buf = NULL; -#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2) +#if defined(CONFIG_SYS_FSL_DDR3) || \ + defined(CONFIG_SYS_FSL_DDR2) || \ + defined(CONFIG_SYS_FSL_DDR4) const struct dynamic_odt *pdodt = odt_unknown; #endif ulong ddr_freq; @@ -519,73 +521,76 @@ unsigned int populate_memctl_options(int all_dimms_registered, if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) buf = buffer; -#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2) +#if defined(CONFIG_SYS_FSL_DDR3) || \ + defined(CONFIG_SYS_FSL_DDR2) || \ + defined(CONFIG_SYS_FSL_DDR4) /* Chip select options. */ - if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) { - switch (pdimm[0].n_ranks) { - case 1: - pdodt = single_S; - break; +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) + switch (pdimm[0].n_ranks) { + case 1: + pdodt = single_S; + break; + case 2: + pdodt = single_D; + break; + case 4: + pdodt = single_Q; + break; + } +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) + switch (pdimm[0].n_ranks) { +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE + case 4: + pdodt = single_Q; + if (pdimm[1].n_ranks) + printf("Error: Quad- and Dual-rank DIMMs cannot be used together\n"); + break; +#endif + case 2: + switch (pdimm[1].n_ranks) { case 2: - pdodt = single_D; + pdodt = dual_DD; break; - case 4: - pdodt = single_Q; + case 1: + pdodt = dual_DS; break; - } - } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) { - switch (pdimm[0].n_ranks) { -#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE - case 4: - pdodt = single_Q; - if (pdimm[1].n_ranks) - printf("Error: Quad- and Dual-rank DIMMs " - "cannot be used together\n"); + case 0: + pdodt = dual_D0; break; -#endif + } + break; + case 1: + switch (pdimm[1].n_ranks) { case 2: - switch (pdimm[1].n_ranks) { - case 2: - pdodt = dual_DD; - break; - case 1: - pdodt = dual_DS; - break; - case 0: - pdodt = dual_D0; - break; - } + pdodt = dual_SD; break; case 1: - switch (pdimm[1].n_ranks) { - case 2: - pdodt = dual_SD; - break; - case 1: - pdodt = dual_SS; - break; - case 0: - pdodt = dual_S0; - break; - } + pdodt = dual_SS; break; case 0: - switch (pdimm[1].n_ranks) { - case 2: - pdodt = dual_0D; - break; - case 1: - pdodt = dual_0S; - break; - } + pdodt = dual_S0; + break; + } + break; + case 0: + switch (pdimm[1].n_ranks) { + case 2: + pdodt = dual_0D; + break; + case 1: + pdodt = dual_0S; break; } + break; } -#endif +#endif /* CONFIG_DIMM_SLOTS_PER_CTLR */ +#endif /* CONFIG_SYS_FSL_DDR2, 3, 4 */ /* Pick chip-select local options. */ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { -#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2) +#if defined(CONFIG_SYS_FSL_DDR3) || \ + defined(CONFIG_SYS_FSL_DDR2) || \ + defined(CONFIG_SYS_FSL_DDR4) popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg; popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg; popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm; @@ -635,7 +640,7 @@ unsigned int populate_memctl_options(int all_dimms_registered, popts->ba_intlv_ctl = 0; /* Memory Organization Parameters */ - popts->registered_dimm_en = all_dimms_registered; + popts->registered_dimm_en = common_dimm->all_dimms_registered; /* Operational Mode Paramters */ @@ -703,7 +708,7 @@ unsigned int populate_memctl_options(int all_dimms_registered, popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0; /* Choose burst length. */ -#if defined(CONFIG_SYS_FSL_DDR3) +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) #if defined(CONFIG_E500MC) popts->otf_burst_chop_en = 0; /* on-the-fly burst chop disable */ popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */ @@ -722,12 +727,17 @@ unsigned int populate_memctl_options(int all_dimms_registered, #endif /* Choose ddr controller address mirror mode */ -#if defined(CONFIG_SYS_FSL_DDR3) - popts->mirrored_dimm = pdimm[0].mirrored_dimm; +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) + for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { + if (pdimm[i].n_ranks) { + popts->mirrored_dimm = pdimm[i].mirrored_dimm; + break; + } + } #endif /* Global Timing Parameters. */ - debug("mclk_ps = %u ps\n", get_memory_clk_period_ps()); + debug("mclk_ps = %u ps\n", get_memory_clk_period_ps(ctrl_num)); /* Pick a caslat override. */ popts->cas_latency_override = 0; @@ -766,17 +776,13 @@ unsigned int populate_memctl_options(int all_dimms_registered, * BSTTOPRE precharge interval * * Set this to 0 for global auto precharge - * - * FIXME: Should this be configured in picoseconds? - * Why it should be in ps: better understanding of this - * relative to actual DRAM timing parameters such as tRAS. - * e.g. tRAS(min) = 40 ns + * The value of 0x100 has been used for DDR1, DDR2, DDR3. + * It is not wrong. Any value should be OK. The performance depends on + * applications. There is no one good value for all. One way to set + * is to use 1/4 of refint value. */ - popts->bstopre = 0x100; - - /* Minimum CKE pulse width -- tCKE(MIN) */ - popts->tcke_clock_pulse_width_ps - = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR); + popts->bstopre = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps) + >> 2; /* * Window for four activates -- tFAW @@ -786,7 +792,7 @@ unsigned int populate_memctl_options(int all_dimms_registered, * FIXME: width, was considering looking at pdimm->primary_sdram_width */ #if defined(CONFIG_SYS_FSL_DDR1) - popts->tfaw_window_four_activates_ps = mclk_to_picos(1); + popts->tfaw_window_four_activates_ps = mclk_to_picos(ctrl_num, 1); #elif defined(CONFIG_SYS_FSL_DDR2) /* @@ -795,12 +801,12 @@ unsigned int populate_memctl_options(int all_dimms_registered, */ popts->tfaw_window_four_activates_ps = 37500; -#elif defined(CONFIG_SYS_FSL_DDR3) +#else popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps; #endif popts->zq_en = 0; popts->wrlvl_en = 0; -#if defined(CONFIG_SYS_FSL_DDR3) +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) /* * due to ddr3 dimm is fly-by topology * we suggest to enable write leveling to @@ -818,21 +824,32 @@ unsigned int populate_memctl_options(int all_dimms_registered, * If memory controller interleaving is enabled, then the data * bus widths must be programmed identically for all memory controllers. * - * XXX: Attempt to set all controllers to the same chip select + * Attempt to set all controllers to the same chip select * interleaving mode. It will do a best effort to get the * requested ranks interleaved together such that the result * should be a subset of the requested configuration. + * + * if CONFIG_SYS_FSL_DDR_INTLV_256B is defined, mandatory interleaving + * with 256 Byte is enabled. */ #if (CONFIG_NUM_DDR_CONTROLLERS > 1) if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) +#ifdef CONFIG_SYS_FSL_DDR_INTLV_256B + ; +#else goto done; - +#endif if (pdimm[0].n_ranks == 0) { printf("There is no rank on CS0 for controller %d.\n", ctrl_num); popts->memctl_interleaving = 0; goto done; } popts->memctl_interleaving = 1; +#ifdef CONFIG_SYS_FSL_DDR_INTLV_256B + popts->memctl_interleaving_mode = FSL_DDR_256B_INTERLEAVING; + popts->memctl_interleaving = 1; + debug("256 Byte interleaving\n"); +#else /* * test null first. if CONFIG_HWCONFIG is not defined * hwconfig_arg_cmp returns non-zero @@ -914,8 +931,9 @@ unsigned int populate_memctl_options(int all_dimms_registered, popts->memctl_interleaving = 0; printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); } +#endif /* CONFIG_SYS_FSL_DDR_INTLV_256B */ done: -#endif +#endif /* CONFIG_NUM_DDR_CONTROLLERS > 1 */ if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) && (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) { /* test null first. if CONFIG_HWCONFIG is not defined, @@ -1025,7 +1043,7 @@ done: if (pdimm[0].n_ranks == 4) popts->quad_rank_present = 1; - ddr_freq = get_ddr_freq(0) / 1000000; + ddr_freq = get_ddr_freq(ctrl_num) / 1000000; if (popts->registered_dimm_en) { popts->rcw_override = 1; popts->rcw_1 = 0x000a5a00; @@ -1050,18 +1068,21 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo) unsigned int check_intlv, check_n_row_addr, check_n_col_addr; unsigned long long check_rank_density; struct dimm_params_s *dimm; + int first_ctrl = pinfo->first_ctrl; + int last_ctrl = first_ctrl + pinfo->num_ctrls - 1; + /* * Check if all controllers are configured for memory * controller interleaving. Identical dimms are recommended. At least * the size, row and col address should be checked. */ j = 0; - check_n_ranks = pinfo->dimm_params[0][0].n_ranks; - check_rank_density = pinfo->dimm_params[0][0].rank_density; - check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr; - check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr; - check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode; - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + check_n_ranks = pinfo->dimm_params[first_ctrl][0].n_ranks; + check_rank_density = pinfo->dimm_params[first_ctrl][0].rank_density; + check_n_row_addr = pinfo->dimm_params[first_ctrl][0].n_row_addr; + check_n_col_addr = pinfo->dimm_params[first_ctrl][0].n_col_addr; + check_intlv = pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode; + for (i = first_ctrl; i <= last_ctrl; i++) { dimm = &pinfo->dimm_params[i][0]; if (!pinfo->memctl_opts[i].memctl_interleaving) { continue; @@ -1079,20 +1100,22 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo) } if (intlv_invalid) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) + for (i = first_ctrl; i <= last_ctrl; i++) pinfo->memctl_opts[i].memctl_interleaving = 0; printf("Not all DIMMs are identical. " "Memory controller interleaving disabled.\n"); } else { switch (check_intlv) { + case FSL_DDR_256B_INTERLEAVING: case FSL_DDR_CACHE_LINE_INTERLEAVING: case FSL_DDR_PAGE_INTERLEAVING: case FSL_DDR_BANK_INTERLEAVING: case FSL_DDR_SUPERBANK_INTERLEAVING: - if (3 == CONFIG_NUM_DDR_CONTROLLERS) +#if (3 == CONFIG_NUM_DDR_CONTROLLERS) k = 2; - else +#else k = CONFIG_NUM_DDR_CONTROLLERS; +#endif break; case FSL_DDR_3WAY_1KB_INTERLEAVING: case FSL_DDR_3WAY_4KB_INTERLEAVING: @@ -1106,10 +1129,10 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo) } debug("%d of %d controllers are interleaving.\n", j, k); if (j && (j != k)) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) + for (i = first_ctrl; i <= last_ctrl; i++) pinfo->memctl_opts[i].memctl_interleaving = 0; - printf("Not all controllers have compatible " - "interleaving mode. All disabled.\n"); + if ((last_ctrl - first_ctrl) > 1) + puts("Not all controllers have compatible interleaving mode. All disabled.\n"); } } debug("Checking interleaving options completed\n");