fsl/ddr: Add erratum_a009942_check_cpo and clean related erratum

- add additional function erratum_a009942_check_cpo to check if the
  board needs tuning CPO calibration for optimal setting.
- move ERRATUM_A009942(with revision to check cpo_sample option) from
  fsl_ddr_gen4.c to ctrl_regs.c for reuse on all DDR4/DDR3 parts.
- move ERRATUM_A008378 from fsl_ddr_gen4.c to ctrl_regs.c
- remove obsolete ERRATUM_A004934 which is replaced with ERRATUM_A009942.

Signed-off-by: Shengzhou Liu <Shengzhou.Liu@nxp.com>
[YS: Replaced CONFIG_QEMU_E500 with CONFIG_ARCH_QEMU_E500]
Reviewed-by: York Sun <york.sun@nxp.com>
master
Shengzhou Liu 8 years ago committed by York Sun
parent 5a17b8b5da
commit 02fb276157
  1. 7
      arch/arm/cpu/armv8/fsl-layerscape/cpu.c
  2. 8
      arch/powerpc/cpu/mpc85xx/cpu_init.c
  3. 2
      arch/powerpc/include/asm/config_mpc85xx.h
  4. 6
      board/freescale/ls1021aqds/ls1021aqds.c
  5. 136
      drivers/ddr/fsl/ctrl_regs.c
  6. 26
      drivers/ddr/fsl/fsl_ddr_gen4.c
  7. 3
      drivers/ddr/fsl/mpc85xx_ddr_gen3.c
  8. 2
      include/fsl_ddr.h
  9. 3
      include/fsl_ddr_sdram.h

@ -26,6 +26,9 @@
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
#include <asm/armv8/sec_firmware.h>
#endif
#ifdef CONFIG_SYS_FSL_DDR
#include <fsl_ddr.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
@ -403,7 +406,9 @@ int arch_early_init_r(void)
#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
erratum_a009635();
#endif
#if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR)
erratum_a009942_check_cpo();
#endif
#ifdef CONFIG_MP
#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && defined(CONFIG_ARMV8_PSCI)
/* Check the psci version to determine if the psci is supported */

@ -45,7 +45,9 @@
#include <nand.h>
#include <errno.h>
#endif
#ifndef CONFIG_ARCH_QEMU_E500
#include <fsl_ddr.h>
#endif
#include "../../../../drivers/block/fsl_sata.h"
#ifdef CONFIG_U_QE
#include <fsl_qe.h>
@ -947,6 +949,10 @@ int cpu_init_r(void)
#endif /* CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE */
#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
erratum_a009942_check_cpo();
#endif
#ifdef CONFIG_FMAN_ENET
fman_enet_init();
#endif

@ -512,7 +512,6 @@
#define CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE
#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
#define CONFIG_SYS_FSL_ERRATUM_A004468
#define CONFIG_SYS_FSL_ERRATUM_A_004934
#define CONFIG_SYS_FSL_ERRATUM_A005871
#define CONFIG_SYS_FSL_ERRATUM_A006379
#define CONFIG_SYS_FSL_ERRATUM_A007186
@ -549,7 +548,6 @@
#define CONFIG_SYS_FSL_TBCLK_DIV 16
#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.4"
#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
#define CONFIG_SYS_FSL_ERRATUM_A_004934
#define CONFIG_SYS_FSL_ERRATUM_A005871
#define CONFIG_SYS_FSL_ERRATUM_A006379
#define CONFIG_SYS_FSL_ERRATUM_A007186

@ -22,7 +22,7 @@
#include <spl.h>
#include <fsl_devdis.h>
#include <fsl_validate.h>
#include <fsl_ddr.h>
#include "../common/sleep.h"
#include "../common/qixis.h"
#include "ls1021aqds_qixis.h"
@ -433,7 +433,9 @@ int board_init(void)
#ifdef CONFIG_SYS_FSL_ERRATUM_A010315
erratum_a010315();
#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
erratum_a009942_check_cpo();
#endif
major = get_soc_major_rev();
if (major == SOC_MAJOR_VER_1_0) {
/* Set CCI-400 control override register to

@ -5,14 +5,14 @@
*/
/*
* Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
* Generic driver for Freescale DDR/DDR2/DDR3/DDR4 memory controller.
* Based on code from spd_sdram.c
* Author: James Yang [at freescale.com]
*/
#include <common.h>
#include <fsl_ddr_sdram.h>
#include <fsl_errata.h>
#include <fsl_ddr.h>
#include <fsl_immap.h>
#include <asm/io.h>
@ -2306,6 +2306,38 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
unsigned int ip_rev = 0;
unsigned int unq_mrs_en = 0;
int cs_en = 1;
#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
unsigned int ddr_freq;
#endif
#if (defined(CONFIG_SYS_FSL_ERRATUM_A008378) && \
defined(CONFIG_SYS_FSL_DDRC_GEN4)) || \
defined(CONFIG_SYS_FSL_ERRATUM_A009942)
struct ccsr_ddr __iomem *ddrc;
switch (ctrl_num) {
case 0:
ddrc = (void *)CONFIG_SYS_FSL_DDR_ADDR;
break;
#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
case 1:
ddrc = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
break;
#endif
#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
case 2:
ddrc = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
break;
#endif
#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
case 3:
ddrc = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
break;
#endif
default:
printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num);
return 1;
}
#endif
memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
@ -2526,5 +2558,105 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
ddr->debug[2] |= 0x00000200; /* set bit 22 */
#endif
#if defined(CONFIG_SYS_FSL_ERRATUM_A008378) && defined(CONFIG_SYS_FSL_DDRC_GEN4)
/* Erratum applies when accumulated ECC is used, or DBI is enabled */
#define IS_ACC_ECC_EN(v) ((v) & 0x4)
#define IS_DBI(v) ((((v) >> 12) & 0x3) == 0x2)
if (has_erratum_a008378()) {
if (IS_ACC_ECC_EN(ddr->ddr_sdram_cfg) ||
IS_DBI(ddr->ddr_sdram_cfg_3)) {
ddr->debug[28] = ddr_in32(&ddrc->debug[28]);
ddr->debug[28] |= (0x9 << 20);
}
}
#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
ddr->debug[28] |= ddr_in32(&ddrc->debug[28]);
ddr->debug[28] &= 0xff0fff00;
if (ddr_freq <= 1333)
ddr->debug[28] |= 0x0080006a;
else if (ddr_freq <= 1600)
ddr->debug[28] |= 0x0070006f;
else if (ddr_freq <= 1867)
ddr->debug[28] |= 0x00700076;
else if (ddr_freq <= 2133)
ddr->debug[28] |= 0x0060007b;
if (popts->cpo_sample)
ddr->debug[28] = (ddr->debug[28] & 0xffffff00) |
popts->cpo_sample;
#endif
return check_fsl_memctl_config_regs(ddr);
}
#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
/*
* This additional workaround of A009942 checks the condition to determine if
* the CPO value set by the existing A009942 workaround needs to be updated.
* If need, print a warning to prompt user reconfigure DDR debug_29[24:31] with
* expected optimal value, the optimal value is highly board dependent.
*/
void erratum_a009942_check_cpo(void)
{
struct ccsr_ddr __iomem *ddr =
(struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR);
u32 cpo, cpo_e, cpo_o, cpo_target, cpo_optimal;
u32 cpo_min = ddr_in32(&ddr->debug[9]) >> 24;
u32 cpo_max = cpo_min;
u32 sdram_cfg, i, tmp, lanes, ddr_type;
bool update_cpo = false, has_ecc = false;
sdram_cfg = ddr_in32(&ddr->sdram_cfg);
if (sdram_cfg & SDRAM_CFG_32_BE)
lanes = 4;
else if (sdram_cfg & SDRAM_CFG_16_BE)
lanes = 2;
else
lanes = 8;
if (sdram_cfg & SDRAM_CFG_ECC_EN)
has_ecc = true;
/* determine the maximum and minimum CPO values */
for (i = 9; i < 9 + lanes / 2; i++) {
cpo = ddr_in32(&ddr->debug[i]);
cpo_e = cpo >> 24;
cpo_o = (cpo >> 8) & 0xff;
tmp = min(cpo_e, cpo_o);
if (tmp < cpo_min)
cpo_min = tmp;
tmp = max(cpo_e, cpo_o);
if (tmp > cpo_max)
cpo_max = tmp;
}
if (has_ecc) {
cpo = ddr_in32(&ddr->debug[13]);
cpo = cpo >> 24;
if (cpo < cpo_min)
cpo_min = cpo;
if (cpo > cpo_max)
cpo_max = cpo;
}
cpo_target = ddr_in32(&ddr->debug[28]) & 0xff;
cpo_optimal = ((cpo_max + cpo_min) >> 1) + 0x27;
debug("cpo_optimal = 0x%x, cpo_target = 0x%x\n", cpo_optimal,
cpo_target);
debug("cpo_max = 0x%x, cpo_min = 0x%x\n", cpo_max, cpo_min);
ddr_type = (sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
SDRAM_CFG_SDRAM_TYPE_SHIFT;
if (ddr_type == SDRAM_TYPE_DDR4)
update_cpo = (cpo_min + 0x3b) < cpo_target ? true : false;
else if (ddr_type == SDRAM_TYPE_DDR3)
update_cpo = (cpo_min + 0x3f) < cpo_target ? true : false;
if (update_cpo) {
printf("WARN: pls set popts->cpo_sample = 0x%x ", cpo_optimal);
printf("in <board>/ddr.c to optimize cpo\n");
}
}
#endif

@ -64,9 +64,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
#ifdef CONFIG_FSL_DDR_BIST
char buffer[CONFIG_SYS_CBSIZE];
#endif
#if defined(CONFIG_SYS_FSL_ERRATUM_A009942)
u32 ddr_freq;
#endif
switch (ctrl_num) {
case 0:
ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
@ -223,16 +220,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->debug[i], regs->debug[i]);
}
}
#ifdef CONFIG_SYS_FSL_ERRATUM_A008378
/* Erratum applies when accumulated ECC is used, or DBI is enabled */
#define IS_ACC_ECC_EN(v) ((v) & 0x4)
#define IS_DBI(v) ((((v) >> 12) & 0x3) == 0x2)
if (has_erratum_a008378()) {
if (IS_ACC_ECC_EN(regs->ddr_sdram_cfg) ||
IS_DBI(regs->ddr_sdram_cfg_3))
ddr_setbits32(&ddr->debug[28], 0x9 << 20);
}
#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
/* Part 1 of 2 */
@ -270,19 +257,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->debug[25], temp32);
#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
temp32 = ddr_in32(&ddr->debug[28]);
if (ddr_freq <= 1333)
ddr_out32(&ddr->debug[28], temp32 | 0x0080006a);
else if (ddr_freq <= 1600)
ddr_out32(&ddr->debug[28], temp32 | 0x0070006f);
else if (ddr_freq <= 1867)
ddr_out32(&ddr->debug[28], temp32 | 0x00700076);
else if (ddr_freq <= 2133)
ddr_out32(&ddr->debug[28], temp32 | 0x0060007b);
#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A010165
temp32 = get_ddr_freq(ctrl_num) / 1000000;
if ((temp32 > 1900) && (temp32 < 2300)) {

@ -174,9 +174,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
out_be32(&ddr->debug[i], regs->debug[i]);
}
}
#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934
out_be32(&ddr->debug[28], 0x30003000);
#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474
out_be32(&ddr->debug[12], 0x00000015);

@ -138,4 +138,6 @@ int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
void update_spd_address(unsigned int ctrl_num,
unsigned int slot,
unsigned int *addr);
void erratum_a009942_check_cpo(void);
#endif

@ -374,7 +374,8 @@ typedef struct memctl_options_s {
unsigned int additive_latency_override_value;
unsigned int clk_adjust; /* */
unsigned int cpo_override;
unsigned int cpo_override; /* override timing_cfg_2[CPO]*/
unsigned int cpo_sample; /* optimize debug_29[24:31] */
unsigned int write_data_delay; /* DQS adjust */
unsigned int cswl_override;

Loading…
Cancel
Save