diff options
Diffstat (limited to 'drivers/ddr')
| -rw-r--r-- | drivers/ddr/fsl/ctrl_regs.c | 55 | ||||
| -rw-r--r-- | drivers/ddr/fsl/fsl_ddr_gen4.c | 44 | ||||
| -rw-r--r-- | drivers/ddr/fsl/options.c | 15 | 
3 files changed, 102 insertions, 12 deletions
| diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 0bfcd3413c6..9073917914e 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -895,11 +895,15 @@ static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num,  	slow = get_ddr_freq(ctrl_num) < 1249000000;  #endif -	if (popts->registered_dimm_en) { +	if (popts->registered_dimm_en)  		rcw_en = 1; -		ap_en = popts->ap_en; -	} else { + +	/* DDR4 can have address parity for UDIMM and discrete */ +	if ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) && +	    (!popts->registered_dimm_en)) {  		ap_en = 0; +	} else { +		ap_en = popts->ap_en;  	}  	x4_en = popts->x4_en ? 1 : 0; @@ -1135,6 +1139,7 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,  	unsigned short esdmode5;	/* Extended SDRAM mode 5 */  	int rtt_park = 0;  	bool four_cs = false; +	const unsigned int mclk_ps = get_memory_clk_period_ps(0);  #if CONFIG_CHIP_SELECTS_PER_CTRL == 4  	if ((ddr->cs[0].config & SDRAM_CS_CONFIG_EN) && @@ -1150,6 +1155,19 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,  		esdmode5 = 0x00000400;	/* Data mask enabled */  	} +	/* set command/address parity latency */ +	if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { +		if (mclk_ps >= 935) { +			/* for DDR4-1600/1866/2133 */ +			esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; +		} else if (mclk_ps >= 833) { +			/* for DDR4-2400 */ +			esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; +		} else { +			printf("parity: mclk_ps = %d not supported\n", mclk_ps); +		} +	} +  	ddr->ddr_sdram_mode_9 = (0  				 | ((esdmode4 & 0xffff) << 16)  				 | ((esdmode5 & 0xffff) << 0) @@ -1170,6 +1188,20 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,  			} else {  				esdmode5 = 0x00000400;  			} + +			if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { +				if (mclk_ps >= 935) { +					/* for DDR4-1600/1866/2133 */ +					esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; +				} else if (mclk_ps >= 833) { +					/* for DDR4-2400 */ +					esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; +				} else { +					printf("parity: mclk_ps = %d not supported\n", +					       mclk_ps); +				} +			} +  			switch (i) {  			case 1:  				ddr->ddr_sdram_mode_11 = (0 @@ -1925,12 +1957,25 @@ static void set_timing_cfg_7(const unsigned int ctrl_num,  			     const common_timing_params_t *common_dimm)  {  	unsigned int txpr, tcksre, tcksrx; -	unsigned int cke_rst, cksre, cksrx, par_lat, cs_to_cmd; +	unsigned int cke_rst, cksre, cksrx, par_lat = 0, cs_to_cmd; +	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);  	txpr = max(5U, picos_to_mclk(ctrl_num, common_dimm->trfc1_ps + 10000));  	tcksre = max(5U, picos_to_mclk(ctrl_num, 10000));  	tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000)); -	par_lat = 0; + +	if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { +		if (mclk_ps >= 935) { +			/* parity latency 4 clocks in case of 1600/1866/2133 */ +			par_lat = 4; +		} else if (mclk_ps >= 833) { +			/* parity latency 5 clocks for DDR4-2400 */ +			par_lat = 5; +		} else { +			printf("parity: mclk_ps = %d not supported\n", mclk_ps); +		} +	} +  	cs_to_cmd = 0;  	if (txpr <= 200) diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 6f76980d319..608810d4e29 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -12,7 +12,8 @@  #include <fsl_ddr.h>  #include <fsl_errata.h> -#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008511) | \ +	defined(CONFIG_SYS_FSL_ERRATUM_A009803)  static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)  {  	int timeout = 1000; @@ -24,9 +25,9 @@ static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)  		timeout--;  	}  	if (timeout <= 0) -		puts("Error: A007865 wait for clear timeout.\n"); +		puts("Error: wait for clear timeout.\n");  } -#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ +#endif  #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)  #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL @@ -201,7 +202,18 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,  		ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);  		ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);  	} + +#ifdef CONFIG_SYS_FSL_ERRATUM_A009803 +	/* part 1 of 2 */ +	if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { /* for RDIMM */ +		ddr_out32(&ddr->ddr_sdram_rcw_2, +			  regs->ddr_sdram_rcw_2 & ~0x0f000000); +	} + +	ddr_out32(&ddr->err_disable, regs->err_disable | DDR_ERR_DISABLE_APED); +#else  	ddr_out32(&ddr->err_disable, regs->err_disable); +#endif  	ddr_out32(&ddr->err_int_en, regs->err_int_en);  	for (i = 0; i < 32; i++) {  		if (regs->debug[i]) { @@ -297,7 +309,8 @@ step2:  	mb();  	isb(); -#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008511) || \ +	defined(CONFIG_SYS_FSL_ERRATUM_A009803)  	/* Part 2 of 2 */  	/* This erraum only applies to verion 5.2.0 */  	if (fsl_ddr_get_version(ctrl_num) == 0x50200) { @@ -313,6 +326,7 @@ step2:  			       ctrl_num, ddr_in32(&ddr->debug[1]));  		} +#ifdef CONFIG_SYS_FSL_ERRATUM_A008511  		/* The vref setting sequence is different for range 2 */  		if (regs->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2)  			vref_seq = vref_seq2; @@ -359,9 +373,29 @@ step2:  		}  		/* Restore D_INIT */  		ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); -	}  #endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009803 +		/* if it's RDIMM */ +		if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { +			for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { +				if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN)) +					continue; +				set_wait_for_bits_clear(&ddr->sdram_md_cntl, +							MD_CNTL_MD_EN | +							MD_CNTL_CS_SEL(i) | +							0x070000ed, +							MD_CNTL_MD_EN); +				udelay(1); +			} +		} + +		ddr_out32(&ddr->err_disable, +			  regs->err_disable & ~DDR_ERR_DISABLE_APED); +#endif +	} +#endif +  	total_gb_size_per_controller = 0;  	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {  		if (!(regs->cs[i].config & 0x80000000)) diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 791d6441010..d0075ff1fd2 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -1002,8 +1002,19 @@ unsigned int populate_memctl_options(const common_timing_params_t *common_dimm,  	popts->twot_en = 0;  	popts->threet_en = 0; -	/* for RDIMM, address parity enable */ -	popts->ap_en = 1; +	/* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */ +	if (popts->registered_dimm_en) +		popts->ap_en = 1; /* 0 = disable,  1 = enable */ +	else +		popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */ + +	if (hwconfig_sub_f("fsl_ddr", "parity", buf)) { +		if (hwconfig_subarg_cmp_f("fsl_ddr", "parity", "on", buf)) { +			if (popts->registered_dimm_en || +			    (CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4)) +				popts->ap_en = 1; +		} +	}  	/*  	 * BSTTOPRE precharge interval | 
