mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-10-02 01:20:47 +09:00
mpc85xx: Implement workaround for erratum DDR-A003
Erratum DDR-A003 requires workaround to correctly set RCW10 for registered DIMM. Also adding polling after enabling DDR controller to ensure completion. Signed-off-by: York Sun <yorksun@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
parent
e1fd16b6f5
commit
fa8d23c0ee
@ -68,6 +68,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||||||
#ifdef CONFIG_SYS_FSL_ERRATUM_ELBC_A001
|
#ifdef CONFIG_SYS_FSL_ERRATUM_ELBC_A001
|
||||||
puts("Work-around for Erratum ELBC-A001 enabled\n");
|
puts("Work-around for Erratum ELBC-A001 enabled\n");
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003
|
||||||
|
puts("Work-around for Erratum DDR-A003 enabled\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,82 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
|
|||||||
temp_sdram_cfg = regs->ddr_sdram_cfg;
|
temp_sdram_cfg = regs->ddr_sdram_cfg;
|
||||||
temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
|
temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
|
||||||
out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
|
out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
|
||||||
|
#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003
|
||||||
|
if (regs->ddr_sdram_rcw_2 & 0x00f00000) {
|
||||||
|
out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff);
|
||||||
|
out_be32(&ddr->debug[2], 0x00000400);
|
||||||
|
out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff);
|
||||||
|
out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff);
|
||||||
|
out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb);
|
||||||
|
out_be32(&ddr->mtcr, 0);
|
||||||
|
out_be32(&ddr->debug[12], 0x00000015);
|
||||||
|
out_be32(&ddr->debug[21], 0x24000000);
|
||||||
|
out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff);
|
||||||
|
out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN);
|
||||||
|
|
||||||
|
asm volatile("sync;isync");
|
||||||
|
while (!(in_be32(&ddr->debug[1]) & 0x2))
|
||||||
|
;
|
||||||
|
|
||||||
|
switch (regs->ddr_sdram_rcw_2 & 0x00f00000) {
|
||||||
|
case 0x00000000:
|
||||||
|
out_be32(&ddr->sdram_md_cntl,
|
||||||
|
MD_CNTL_MD_EN |
|
||||||
|
MD_CNTL_CS_SEL_CS0_CS1 |
|
||||||
|
0x04000000 |
|
||||||
|
MD_CNTL_WRCW |
|
||||||
|
MD_CNTL_MD_VALUE(0x02));
|
||||||
|
break;
|
||||||
|
case 0x00100000:
|
||||||
|
out_be32(&ddr->sdram_md_cntl,
|
||||||
|
MD_CNTL_MD_EN |
|
||||||
|
MD_CNTL_CS_SEL_CS0_CS1 |
|
||||||
|
0x04000000 |
|
||||||
|
MD_CNTL_WRCW |
|
||||||
|
MD_CNTL_MD_VALUE(0x0a));
|
||||||
|
break;
|
||||||
|
case 0x00200000:
|
||||||
|
out_be32(&ddr->sdram_md_cntl,
|
||||||
|
MD_CNTL_MD_EN |
|
||||||
|
MD_CNTL_CS_SEL_CS0_CS1 |
|
||||||
|
0x04000000 |
|
||||||
|
MD_CNTL_WRCW |
|
||||||
|
MD_CNTL_MD_VALUE(0x12));
|
||||||
|
break;
|
||||||
|
case 0x00300000:
|
||||||
|
out_be32(&ddr->sdram_md_cntl,
|
||||||
|
MD_CNTL_MD_EN |
|
||||||
|
MD_CNTL_CS_SEL_CS0_CS1 |
|
||||||
|
0x04000000 |
|
||||||
|
MD_CNTL_WRCW |
|
||||||
|
MD_CNTL_MD_VALUE(0x1a));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
out_be32(&ddr->sdram_md_cntl,
|
||||||
|
MD_CNTL_MD_EN |
|
||||||
|
MD_CNTL_CS_SEL_CS0_CS1 |
|
||||||
|
0x04000000 |
|
||||||
|
MD_CNTL_WRCW |
|
||||||
|
MD_CNTL_MD_VALUE(0x02));
|
||||||
|
printf("Unsupported RC10\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (in_be32(&ddr->sdram_md_cntl) & 0x80000000)
|
||||||
|
;
|
||||||
|
udelay(6);
|
||||||
|
out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
|
||||||
|
out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
|
||||||
|
out_be32(&ddr->debug[2], 0x0);
|
||||||
|
out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
|
||||||
|
out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
|
||||||
|
out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
|
||||||
|
out_be32(&ddr->debug[12], 0x0);
|
||||||
|
out_be32(&ddr->debug[21], 0x0);
|
||||||
|
out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* For 8572 DDR1 erratum - DDR controller may enter illegal state
|
* For 8572 DDR1 erratum - DDR controller may enter illegal state
|
||||||
* when operatiing in 32-bit bus mode with 4-beat bursts,
|
* when operatiing in 32-bit bus mode with 4-beat bursts,
|
||||||
@ -120,8 +196,11 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
|
|||||||
asm volatile("sync;isync");
|
asm volatile("sync;isync");
|
||||||
|
|
||||||
/* Let the controller go */
|
/* Let the controller go */
|
||||||
temp_sdram_cfg = in_be32(&ddr->sdram_cfg);
|
temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
|
||||||
out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
|
out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
|
||||||
|
asm volatile("sync;isync");
|
||||||
|
while (!(in_be32(&ddr->debug[1]) & 0x2))
|
||||||
|
;
|
||||||
|
|
||||||
/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
|
/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
|
||||||
while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
|
while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
|
||||||
|
@ -163,6 +163,7 @@
|
|||||||
#define CONFIG_NUM_DDR_CONTROLLERS 2
|
#define CONFIG_NUM_DDR_CONTROLLERS 2
|
||||||
#define CONFIG_SYS_FSL_ERRATUM_CPC_A002
|
#define CONFIG_SYS_FSL_ERRATUM_CPC_A002
|
||||||
#define CONFIG_SYS_FSL_ERRATUM_CPC_A003
|
#define CONFIG_SYS_FSL_ERRATUM_CPC_A003
|
||||||
|
#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
|
||||||
#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
|
#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
|
||||||
#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
|
#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
|
||||||
#define CONFIG_SYS_FSL_ERRATUM_ESDHC135
|
#define CONFIG_SYS_FSL_ERRATUM_ESDHC135
|
||||||
|
@ -101,6 +101,25 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
|
|||||||
#define WR_DATA_DELAY_SHIFT 10
|
#define WR_DATA_DELAY_SHIFT 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* DDR_MD_CNTL */
|
||||||
|
#define MD_CNTL_MD_EN 0x80000000
|
||||||
|
#define MD_CNTL_CS_SEL_CS0 0x00000000
|
||||||
|
#define MD_CNTL_CS_SEL_CS1 0x10000000
|
||||||
|
#define MD_CNTL_CS_SEL_CS2 0x20000000
|
||||||
|
#define MD_CNTL_CS_SEL_CS3 0x30000000
|
||||||
|
#define MD_CNTL_CS_SEL_CS0_CS1 0x40000000
|
||||||
|
#define MD_CNTL_CS_SEL_CS2_CS3 0x50000000
|
||||||
|
#define MD_CNTL_MD_SEL_MR 0x00000000
|
||||||
|
#define MD_CNTL_MD_SEL_EMR 0x01000000
|
||||||
|
#define MD_CNTL_MD_SEL_EMR2 0x02000000
|
||||||
|
#define MD_CNTL_MD_SEL_EMR3 0x03000000
|
||||||
|
#define MD_CNTL_SET_REF 0x00800000
|
||||||
|
#define MD_CNTL_SET_PRE 0x00400000
|
||||||
|
#define MD_CNTL_CKE_CNTL_LOW 0x00100000
|
||||||
|
#define MD_CNTL_CKE_CNTL_HIGH 0x00200000
|
||||||
|
#define MD_CNTL_WRCW 0x00080000
|
||||||
|
#define MD_CNTL_MD_VALUE(x) (x & 0x0000FFFF)
|
||||||
|
|
||||||
/* Record of register values computed */
|
/* Record of register values computed */
|
||||||
typedef struct fsl_ddr_cfg_regs_s {
|
typedef struct fsl_ddr_cfg_regs_s {
|
||||||
struct {
|
struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user