mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-29 08:01:08 +00:00
arm: emif-common: Add suppport for enabling ECC
For data integrity, the EMIF1 supports ECC on the data written or read from the SDRAM. Add support for enabling ECC support in EMIF1. Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com> Signed-off-by: Krunal Bhargav <k-bhargav@ti.com>
This commit is contained in:
parent
e18cd3d796
commit
650fda93c8
2 changed files with 119 additions and 1 deletions
|
@ -604,6 +604,34 @@
|
|||
|
||||
#define EMIF_EXT_PHY_CTRL_TIMING_REG 0x5
|
||||
|
||||
/* EMIF ECC CTRL reg */
|
||||
#define EMIF_ECC_CTRL_REG_ECC_EN_SHIFT 31
|
||||
#define EMIF_ECC_CTRL_REG_ECC_EN_MASK (1 << 31)
|
||||
#define EMIF_ECC_CTRL_REG_ECC_ADDR_RGN_PROT_SHIFT 30
|
||||
#define EMIF_ECC_CTRL_REG_ECC_ADDR_RGN_PROT_MASK (1 << 30)
|
||||
#define EMIF_ECC_CTRL_REG_ECC_VERIFY_DIS_SHIFT 29
|
||||
#define EMIF_ECC_CTRL_REG_ECC_VERIFY_DIS_MASK (1 << 29)
|
||||
#define EMIF_ECC_REG_RMW_EN_SHIFT 28
|
||||
#define EMIF_ECC_REG_RMW_EN_MASK (1 << 28)
|
||||
#define EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_SHIFT 1
|
||||
#define EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK (1 << 1)
|
||||
#define EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_SHIFT 0
|
||||
#define EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK (1 << 0)
|
||||
|
||||
/* EMIF ECC ADDRESS RANGE */
|
||||
#define EMIF_ECC_REG_ECC_END_ADDR_SHIFT 16
|
||||
#define EMIF_ECC_REG_ECC_END_ADDR_MASK (0xffff << 16)
|
||||
#define EMIF_ECC_REG_ECC_START_ADDR_SHIFT 0
|
||||
#define EMIF_ECC_REG_ECC_START_ADDR_MASK (0xffff << 0)
|
||||
|
||||
/* EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS */
|
||||
#define EMIF_INT_ONEBIT_ECC_ERR_SYS_SHIFT 5
|
||||
#define EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK (1 << 5)
|
||||
#define EMIF_INT_TWOBIT_ECC_ERR_SYS_SHIFT 4
|
||||
#define EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK (1 << 4)
|
||||
#define EMIF_INT_WR_ECC_ERR_SYS_SHIFT 3
|
||||
#define EMIF_INT_WR_ECC_ERR_SYS_MASK (1 << 3)
|
||||
|
||||
/* Reg mapping structure */
|
||||
struct emif_reg_struct {
|
||||
u32 emif_mod_id_rev;
|
||||
|
@ -1205,6 +1233,9 @@ struct emif_regs {
|
|||
u32 emif_connect_id_serv_1_map;
|
||||
u32 emif_connect_id_serv_2_map;
|
||||
u32 emif_cos_config;
|
||||
u32 emif_ecc_ctrl_reg;
|
||||
u32 emif_ecc_address_range_1;
|
||||
u32 emif_ecc_address_range_2;
|
||||
};
|
||||
|
||||
struct lpddr2_mr_regs {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <asm/omap_sec_common.h>
|
||||
#include <asm/utils.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/ti-common/ti-edma3.h>
|
||||
|
||||
static int emif1_enabled = -1, emif2_enabled = -1;
|
||||
|
||||
|
@ -332,6 +333,71 @@ static void dra7_ddr3_leveling(u32 base, const struct emif_regs *regs)
|
|||
update_hwleveling_output(base, regs);
|
||||
}
|
||||
|
||||
static void dra7_reset_ddr_data(u32 base, u32 size)
|
||||
{
|
||||
#if defined(CONFIG_TI_EDMA3) && !defined(CONFIG_DMA)
|
||||
enable_edma3_clocks();
|
||||
|
||||
edma3_fill(EDMA3_BASE, 1, (void *)base, 0, size);
|
||||
|
||||
disable_edma3_clocks();
|
||||
#else
|
||||
memset((void *)base, 0, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dra7_enable_ecc(u32 base, const struct emif_regs *regs)
|
||||
{
|
||||
struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
|
||||
u32 rgn, size;
|
||||
|
||||
/* ECC available only on dra76x EMIF1 */
|
||||
if ((base != EMIF1_BASE) || !is_dra76x())
|
||||
return;
|
||||
|
||||
if (regs->emif_ecc_ctrl_reg & EMIF_ECC_CTRL_REG_ECC_EN_MASK) {
|
||||
writel(regs->emif_ecc_address_range_1,
|
||||
&emif->emif_ecc_address_range_1);
|
||||
writel(regs->emif_ecc_address_range_2,
|
||||
&emif->emif_ecc_address_range_2);
|
||||
writel(regs->emif_ecc_ctrl_reg, &emif->emif_ecc_ctrl_reg);
|
||||
|
||||
/* Set region1 memory with 0 */
|
||||
rgn = ((regs->emif_ecc_address_range_1 &
|
||||
EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) +
|
||||
CONFIG_SYS_SDRAM_BASE;
|
||||
size = (regs->emif_ecc_address_range_1 &
|
||||
EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000;
|
||||
|
||||
if (regs->emif_ecc_ctrl_reg &
|
||||
EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK)
|
||||
dra7_reset_ddr_data(rgn, size);
|
||||
|
||||
/* Set region2 memory with 0 */
|
||||
rgn = ((regs->emif_ecc_address_range_2 &
|
||||
EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) +
|
||||
CONFIG_SYS_SDRAM_BASE;
|
||||
size = (regs->emif_ecc_address_range_2 &
|
||||
EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0x10000;
|
||||
|
||||
if (regs->emif_ecc_ctrl_reg &
|
||||
EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK)
|
||||
dra7_reset_ddr_data(rgn, size);
|
||||
|
||||
#ifdef CONFIG_DRA7XX
|
||||
/* Clear the status flags and other history */
|
||||
writel(readl(&emif->emif_1b_ecc_err_cnt),
|
||||
&emif->emif_1b_ecc_err_cnt);
|
||||
writel(0xffffffff, &emif->emif_1b_ecc_err_dist_1);
|
||||
writel(0x1, &emif->emif_2b_ecc_err_addr_log);
|
||||
writel(EMIF_INT_WR_ECC_ERR_SYS_MASK |
|
||||
EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK |
|
||||
EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK,
|
||||
&emif->emif_irqstatus_sys);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void dra7_ddr3_init(u32 base, const struct emif_regs *regs)
|
||||
{
|
||||
struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
|
||||
|
@ -368,8 +434,29 @@ static void dra7_ddr3_init(u32 base, const struct emif_regs *regs)
|
|||
|
||||
writel(regs->ref_ctrl_final, &emif->emif_sdram_ref_ctrl);
|
||||
|
||||
if (regs->emif_rd_wr_lvl_rmp_ctl & EMIF_REG_RDWRLVL_EN_MASK)
|
||||
if (regs->emif_rd_wr_lvl_rmp_ctl & EMIF_REG_RDWRLVL_EN_MASK) {
|
||||
/*
|
||||
* Perform Dummy ECC setup just to allow hardware
|
||||
* leveling of ECC memories
|
||||
*/
|
||||
if (is_dra76x() && (base == EMIF1_BASE) &&
|
||||
(regs->emif_ecc_ctrl_reg & EMIF_ECC_CTRL_REG_ECC_EN_MASK)) {
|
||||
writel(0, &emif->emif_ecc_address_range_1);
|
||||
writel(0, &emif->emif_ecc_address_range_2);
|
||||
writel(EMIF_ECC_CTRL_REG_ECC_EN_MASK |
|
||||
EMIF_ECC_CTRL_REG_ECC_ADDR_RGN_PROT_MASK,
|
||||
&emif->emif_ecc_ctrl_reg);
|
||||
}
|
||||
|
||||
dra7_ddr3_leveling(base, regs);
|
||||
|
||||
/* Disable ECC */
|
||||
if (is_dra76x())
|
||||
writel(0, &emif->emif_ecc_ctrl_reg);
|
||||
}
|
||||
|
||||
/* Enable ECC as necessary */
|
||||
dra7_enable_ecc(base, regs);
|
||||
}
|
||||
|
||||
static void omap5_ddr3_init(u32 base, const struct emif_regs *regs)
|
||||
|
|
Loading…
Reference in a new issue