From 158097052a6a528408e05d2345ff2ccdbb46036e Mon Sep 17 00:00:00 2001 From: Alison Wang Date: Wed, 6 Mar 2019 14:49:14 +0800 Subject: armv7: ls102xa: Add workaround for DDR erratum A-008850 Barrier transactions from CCI400 need to be disabled till the DDR is configured, otherwise it may lead to system hang. The patch adds workaround to fix the erratum. Signed-off-by: Shengzhou Liu Signed-off-by: Alison Wang Reviewed-by: Prabhakar Kushwaha --- arch/arm/cpu/armv7/ls102xa/soc.c | 44 +++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) (limited to 'arch/arm/cpu/armv7/ls102xa/soc.c') diff --git a/arch/arm/cpu/armv7/ls102xa/soc.c b/arch/arm/cpu/armv7/ls102xa/soc.c index 448d951c36..a779d33739 100644 --- a/arch/arm/cpu/armv7/ls102xa/soc.c +++ b/arch/arm/cpu/armv7/ls102xa/soc.c @@ -11,6 +11,7 @@ #include #include #include +#include struct liodn_id_table sec_liodn_tbl[] = { SET_SEC_JR_LIODN_ENTRY(0, 0x10, 0x10), @@ -103,6 +104,41 @@ static void erratum_a009007(void) #endif /* CONFIG_SYS_FSL_ERRATUM_A009007 */ } +static void erratum_a008850_early(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850 + /* part 1 of 2 */ + struct ccsr_cci400 __iomem *cci = (void *)(CONFIG_SYS_IMMR + + CONFIG_SYS_CCI400_OFFSET); + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + + /* disables propagation of barrier transactions to DDRC from CCI400 */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); + + /* disable the re-ordering in DDRC */ + out_be32(&ddr->eor, DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS); +#endif +} + +void erratum_a008850_post(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850 + /* part 2 of 2 */ + struct ccsr_cci400 __iomem *cci = (void *)(CONFIG_SYS_IMMR + + CONFIG_SYS_CCI400_OFFSET); + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + u32 tmp; + + /* enable propagation of barrier transactions to DDRC from CCI400 */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + + /* enable the re-ordering in DDRC */ + tmp = in_be32(&ddr->eor); + tmp &= ~(DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS); + out_be32(&ddr->eor, tmp); +#endif +} + void s_init(void) { } @@ -163,13 +199,6 @@ int arch_soc_init(void) */ out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE); out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE); - - /* Workaround for the issue that DDR could not respond to - * barrier transaction which is generated by executing DSB/ISB - * instruction. Set CCI-400 control override register to - * terminate the barrier transaction. After DDR is initialized, - * allow barrier transaction to DDR again */ - out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); } /* Enable all the snoop signal for various masters */ @@ -191,6 +220,7 @@ int arch_soc_init(void) out_be32(&scfg->eddrtqcfg, 0x63b20042); /* Erratum */ + erratum_a008850_early(); erratum_a009008(); erratum_a009798(); erratum_a008997(); -- cgit