[U-Boot] [PATCH 1/4] powerpc/mpc8xxx: fix recognition of DIMMs with ECC and Address Parity

From: York Sun yorksun@freescale.com
To recognize DIMMs with ECC capability by testing ECC bit only. Not to be confused by Address Parity bit.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- .../cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 3 ++- arch/powerpc/include/asm/fsl_ddr_dimm_params.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c index a58e5a9..8b31ec0 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c @@ -367,7 +367,8 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, /* Determine if all DIMMs ECC capable. */ temp1 = 1; for (i = 0; i < number_of_dimms; i++) { - if (dimm_params[i].n_ranks && dimm_params[i].edc_config != 2) { + if (dimm_params[i].n_ranks && + !(dimm_params[i].edc_config & EDC_ECC)) { temp1 = 0; break; } diff --git a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h index be82602..982b809 100644 --- a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h +++ b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h @@ -9,6 +9,10 @@ #ifndef DDR2_DIMM_PARAMS_H #define DDR2_DIMM_PARAMS_H
+#define EDC_DATA_PARITY 1 +#define EDC_ECC 2 +#define EDC_AC_PARITY 4 + /* Parameters for a DDR2 dimm computed from the SPD */ typedef struct dimm_params_s {

From: York Sun yorksun@freescale.com
Tested all possible values for clk_adjust and write_data_delay for dual rank UDIMM and RDIMM to revise the tables.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- board/freescale/mpc8572ds/ddr.c | 110 +++++++++++++++++++++++++++----------- 1 files changed, 78 insertions(+), 32 deletions(-)
diff --git a/board/freescale/mpc8572ds/ddr.c b/board/freescale/mpc8572ds/ddr.c index d66ede2..cdde6ec 100644 --- a/board/freescale/mpc8572ds/ddr.c +++ b/board/freescale/mpc8572ds/ddr.c @@ -49,28 +49,27 @@ typedef struct { u32 force_2T; } board_specific_parameters_t;
-/* ranges for parameters: - * wr_data_delay = 0-6 - * clk adjust = 0-8 - * cpo 2-0x1E (30) +/* + * CPO value doesn't matter if workaround for errata 111 and 134 enabled. + * + * For DDR2 DIMM, all combinations of clk_adjust and write_data_delay have been + * tested. For RDIMM, clk_adjust = 4 and write_data_delay = 3 is optimized for + * all clocks from 400MT/s to 800MT/s, verified with Kingston KVR800D2D8P6/2G. + * For UDIMM, clk_adjust = 8 and write_delay = 5 is optimized for all clocks + * from 400MT/s to 800MT/s, verified with Micron MT18HTF25672AY-800E1. */ - - -/* XXX: these values need to be checked for all interleaving modes. */ -/* XXX: No reliable dual-rank 800 MHz setting has been found. It may - * seem reliable, but errors will appear when memory intensive - * program is run. */ -/* XXX: Single rank at 800 MHz is OK. */ -const board_specific_parameters_t board_specific_parameters[][20] = { +const board_specific_parameters_t board_specific_parameters_udimm[][20] = { { - /* memory controller 0 */ - /* lo| hi| num| clk| cpo|wrdata|2T */ - /* mhz| mhz|ranks|adjst| | delay| */ - { 0, 333, 2, 6, 7, 3, 0}, - {334, 400, 2, 6, 9, 3, 0}, - {401, 549, 2, 6, 11, 3, 0}, - {550, 680, 2, 1, 10, 5, 0}, - {681, 850, 2, 1, 12, 5, 1}, + /* + * memory controller 0 + * lo| hi| num| clk| cpo|wrdata|2T + * mhz| mhz|ranks|adjst| | delay| + */ + { 0, 333, 2, 8, 7, 5, 0}, + {334, 400, 2, 8, 9, 5, 0}, + {401, 549, 2, 8, 11, 5, 0}, + {550, 680, 2, 8, 10, 5, 0}, + {681, 850, 2, 8, 12, 5, 1}, { 0, 333, 1, 6, 7, 3, 0}, {334, 400, 1, 6, 9, 3, 0}, {401, 549, 1, 6, 11, 3, 0}, @@ -79,14 +78,16 @@ const board_specific_parameters_t board_specific_parameters[][20] = { },
{ - /* memory controller 1 */ - /* lo| hi| num| clk| cpo|wrdata|2T */ - /* mhz| mhz|ranks|adjst| | delay| */ - { 0, 333, 2, 6, 7, 3, 0}, - {334, 400, 2, 6, 9, 3, 0}, - {401, 549, 2, 6, 11, 3, 0}, - {550, 680, 2, 1, 11, 6, 0}, - {681, 850, 2, 1, 13, 6, 1}, + /* + * memory controller 1 + * lo| hi| num| clk| cpo|wrdata|2T + * mhz| mhz|ranks|adjst| | delay| + */ + { 0, 333, 2, 8, 7, 5, 0}, + {334, 400, 2, 8, 9, 5, 0}, + {401, 549, 2, 8, 11, 5, 0}, + {550, 680, 2, 8, 11, 5, 0}, + {681, 850, 2, 8, 13, 5, 1}, { 0, 333, 1, 6, 7, 3, 0}, {334, 400, 1, 6, 9, 3, 0}, {401, 549, 1, 6, 11, 3, 0}, @@ -95,16 +96,56 @@ const board_specific_parameters_t board_specific_parameters[][20] = { } };
+const board_specific_parameters_t board_specific_parameters_rdimm[][20] = { + { + /* + * memory controller 0 + * lo| hi| num| clk| cpo|wrdata|2T + * mhz| mhz|ranks|adjst| | delay| + */ + { 0, 333, 2, 4, 7, 3, 0}, + {334, 400, 2, 4, 9, 3, 0}, + {401, 549, 2, 4, 11, 3, 0}, + {550, 680, 2, 4, 10, 3, 0}, + {681, 850, 2, 4, 12, 3, 1}, + }, + + { + /* + * memory controller 1 + * lo| hi| num| clk| cpo|wrdata|2T + * mhz| mhz|ranks|adjst| | delay| + */ + { 0, 333, 2, 4, 7, 3, 0}, + {334, 400, 2, 4, 9, 3, 0}, + {401, 549, 2, 4, 11, 3, 0}, + {550, 680, 2, 4, 11, 3, 0}, + {681, 850, 2, 4, 13, 3, 1}, + } +}; + void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, unsigned int ctrl_num) { - const board_specific_parameters_t *pbsp = - &(board_specific_parameters[ctrl_num][0]); - u32 num_params = sizeof(board_specific_parameters[ctrl_num]) / - sizeof(board_specific_parameters[0][0]); + const board_specific_parameters_t *pbsp; + u32 num_params; u32 i; ulong ddr_freq; + int matched = 0; + + if (!pdimm->n_ranks) + return; + + if (popts->registered_dimm_en) { + pbsp = &(board_specific_parameters_rdimm[ctrl_num][0]); + num_params = sizeof(board_specific_parameters_rdimm[ctrl_num]) / + sizeof(board_specific_parameters_rdimm[0][0]); + } else { + pbsp = &(board_specific_parameters_udimm[ctrl_num][0]); + num_params = sizeof(board_specific_parameters_udimm[ctrl_num]) / + sizeof(board_specific_parameters_udimm[0][0]); + }
/* set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If @@ -138,10 +179,15 @@ void fsl_ddr_board_options(memctl_options_t *popts, popts->cpo_override = pbsp->cpo; popts->write_data_delay = pbsp->write_data_delay; popts->twoT_en = pbsp->force_2T; + matched = 1; + break; } pbsp++; }
+ if (!matched) + printf("Warning: board specific timing not found!\n"); + /* * Factors to consider for half-strength driver enable: * - number of DIMMs installed

From: York Sun yorksun@freescale.com
rcw_en bit is only available for DDR3 controllers. It is a reserved bit on DDR1 and DDR2 controllers.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c index 8ef6ca8..cefabe7 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -682,7 +682,9 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, | ((obc_cfg & 0x1) << 6) | ((ap_en & 0x1) << 5) | ((d_init & 0x1) << 4) +#ifdef CONFIG_FSL_DDR3 | ((rcw_en & 0x1) << 2) +#endif | ((md_en & 0x1) << 0) ); debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);

From: York Sun yorksun@freescale.com
The fix for errata workaround is to avoid covering physical address 0xff000000 to 0xffffffff during the implementation.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 41 +++++++++++++++++++++++++++++++++++ 1 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c index 73b320b..c8c84a1 100644 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c +++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c @@ -24,6 +24,8 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR; u32 total_gb_size_per_controller; + unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t; + int csn = -1; #endif
switch (ctrl_num) { @@ -40,6 +42,22 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
out_be32(&ddr->eor, regs->ddr_eor);
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + cs_sa = (regs->cs[i].bnds >> 16) & 0xfff; + cs_ea = regs->cs[i].bnds & 0xfff; + if ((cs_sa <= 0xff) && (cs_ea >= 0xff)) { + csn = i; + csn_bnds_backup = regs->cs[i].bnds; + csn_bnds_t = (unsigned int *) ®s->cs[i].bnds; + *csn_bnds_t = regs->cs[i].bnds ^ 0x0F000F00; + debug("Found cs%d_bns (0x%08x) covering 0xff000000, " + "change it to 0x%x\n", + csn, csn_bnds_backup, regs->cs[i].bnds); + break; + } + } +#endif for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { if (i == 0) { out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); @@ -308,5 +326,28 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, /* 10. Clear EEBACR[3] */ clrbits_be32(&ecm->eebacr, 10000000); debug("Clearing EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); + + if (csn != -1) { + csn_bnds_t = (unsigned int *) ®s->cs[csn].bnds; + *csn_bnds_t = csn_bnds_backup; + debug("Change cs%d_bnds back to 0x%08x\n", + csn, regs->cs[csn].bnds); + setbits_be32(&ddr->sdram_cfg, 0x2); /* MEM_HALT */ + switch (csn) { + case 0: + out_be32(&ddr->cs0_bnds, regs->cs[csn].bnds); + break; + case 1: + out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds); + break; + case 2: + out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds); + break; + case 3: + out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds); + break; + } + clrbits_be32(&ddr->sdram_cfg, 0x2); + } #endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */ }

On Mar 17, 2011, at 3:58 PM, Kumar Gala wrote:
From: York Sun yorksun@freescale.com
The fix for errata workaround is to avoid covering physical address 0xff000000 to 0xffffffff during the implementation.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 41 +++++++++++++++++++++++++++++++++++ 1 files changed, 41 insertions(+), 0 deletions(-)
applied
- k

On Mar 17, 2011, at 3:58 PM, Kumar Gala wrote:
From: York Sun yorksun@freescale.com
rcw_en bit is only available for DDR3 controllers. It is a reserved bit on DDR1 and DDR2 controllers.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
applied
- k

On Mar 17, 2011, at 3:58 PM, Kumar Gala wrote:
From: York Sun yorksun@freescale.com
Tested all possible values for clk_adjust and write_data_delay for dual rank UDIMM and RDIMM to revise the tables.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
board/freescale/mpc8572ds/ddr.c | 110 +++++++++++++++++++++++++++----------- 1 files changed, 78 insertions(+), 32 deletions(-)
applied
- k

On Mar 17, 2011, at 3:58 PM, Kumar Gala wrote:
From: York Sun yorksun@freescale.com
To recognize DIMMs with ECC capability by testing ECC bit only. Not to be confused by Address Parity bit.
Signed-off-by: York Sun yorksun@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
.../cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 3 ++- arch/powerpc/include/asm/fsl_ddr_dimm_params.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletions(-)
applied
- k
participants (1)
-
Kumar Gala