keystone2: ecc: add ddr3 error detection and correction support
Subsystems (2)
v3 cover keystone2: ecc: add ddr3 error detection and correction support
This series adds DDR3 ECC support to enable ECC in the DDR3 EMIF controller for Keystone II devices.
Based on
"[U-boot] [Patch v2 0/6] keystone2: add network support for K2E SoC and EVM"
https://www.mail-archive.com/u-boot at lists.denx.de/msg150359.html
v3..v2:
- ARM: keystone: cmd_ddr3: add ddr3 commands to test ddr corrected due to some applying warnings.
v2..v1:
nothing changed, just rebase
Hao Zhang (1):
ARM: keystone: cmd_ddr3: add ddr3 commands to test ddr
Ivan Khoronzhuk (1):
dma: ti-edma3: introduce edma3 driver
Vitaly Andrianov (2):
ARM: keystone: msmc: extend functionality of SES
keystone2: ecc: add ddr3 error detection and correction support
arch/arm/cpu/armv7/keystone/Makefile | 2 +- arch/arm/cpu/armv7/keystone/cmd_ddr3.c | 248 +++++++++++++ arch/arm/cpu/armv7/keystone/ddr3.c | 244 +++++++++++++ arch/arm/cpu/armv7/keystone/msmc.c | 26 ++ arch/arm/include/asm/arch-keystone/ddr3.h | 6 + arch/arm/include/asm/arch-keystone/hardware-k2hk.h | 4 + arch/arm/include/asm/arch-keystone/hardware.h | 52 +++ arch/arm/include/asm/arch-keystone/msmc.h | 28 ++ arch/arm/include/asm/ti-common/ti-edma3.h | 121 +++++++ board/ti/ks2_evm/board.c | 3 + board/ti/ks2_evm/ddr3_k2hk.c | 16 + drivers/dma/Makefile | 1 + drivers/dma/ti-edma3.c | 384 +++++++++++++++++++++ include/configs/ks2_evm.h | 4 - 14 files changed, 1134 insertions(+), 5 deletions(-) create mode 100644 arch/arm/cpu/armv7/keystone/cmd_ddr3.c create mode 100644 arch/arm/include/asm/ti-common/ti-edma3.h create mode 100644 drivers/dma/ti-edma3.c
Signature · 1 line
1.8.3.2
PATCH v3 1/4 dma: ti-edma3: introduce edma3 driver
The EDMA3 controller?s primary purpose is to service data transfers that you program between two memory-mapped slave endpoints on the device.
Typical usage includes, but is not limited to the following:
- Servicing software-driven paging transfers (e.g., transfers from external memory, such as SDRAM to internal device memory, such as DSP L2 SRAM)
- Servicing event-driven peripherals, such as a serial port
- Performing sorting or sub-frame extraction of various data structures
- Offloading data transfers from the main device DSP(s)
- See the device-specific data manual for specific peripherals that are accessible via the EDMA3 controller
--- arch/arm/include/asm/ti-common/ti-edma3.h | 121 ++++++++++ drivers/dma/Makefile | 1 + drivers/dma/ti-edma3.c | 384 ++++++++++++++++++++++++++++++ 3 files changed, 506 insertions(+) create mode 100644 arch/arm/include/asm/ti-common/ti-edma3.h create mode 100644 drivers/dma/ti-edma3.c
arch/arm/include/asm/ti-common/ti-edma3.h new file +121 -0
@@ -0,0 +1,121 @@ +/* +* Enhanced Direct Memory Access (EDMA3) Controller +* +* (C) Copyright 2014 +* Texas Instruments Incorporated, <www.ti.com> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _EDMA3_H_ +#define _EDMA3_H_ + +#include <linux/stddef.h> + +#define EDMA3_PARSET_NULL_LINK 0xffff + +/* +* All parameter RAM set options +* opt field in edma3_param_set_config structure +*/ +#define EDMA3_SLOPT_PRIV_LEVEL BIT(31) +#define EDMA3_SLOPT_PRIV_ID (id) ((0xf & (id)) << 24) +#define EDMA3_SLOPT_INTERM_COMP_CHAIN_ENB BIT(23) +#define EDMA3_SLOPT_TRANS_COMP_CHAIN_ENB BIT(22) +#define EDMA3_SLOPT_INTERM_COMP_INT_ENB BIT(21) +#define EDMA3_SLOPT_TRANS_COMP_INT_ENB BIT(20) +#define EDMA3_SLOPT_COMP_CODE (code) ((0x3f & (code)) << 12) +#define EDMA3_SLOPT_FIFO_WIDTH_8 0 +#define EDMA3_SLOPT_FIFO_WIDTH_16 (1 << 8) +#define EDMA3_SLOPT_FIFO_WIDTH_32 (2 << 8) +#define EDMA3_SLOPT_FIFO_WIDTH_64 (3 << 8) +#define EDMA3_SLOPT_FIFO_WIDTH_128 (4 << 8) +#define EDMA3_SLOPT_FIFO_WIDTH_256 (5 << 8) +#define EDMA3_SLOPT_FIFO_WIDTH_SET (w) ((w & 0x7) << 8) +#define EDMA3_SLOPT_STATIC BIT(3) +#define EDMA3_SLOPT_AB_SYNC BIT(2) +#define EDMA3_SLOPT_DST_ADDR_CONST_MODE BIT(1) +#define EDMA3_SLOPT_SRC_ADDR_CONST_MODE BIT(0) + +enum edma3_address_mode { +INCR =0 , +FIFO =1 +}; + +enum edma3_fifo_width { +W8BIT =0 , +W16BIT =1 , +W32BIT =2 , +W64BIT =3 , +W128BIT =4 , +W256BIT =5 +}; + +enum edma3_sync_dimension { +ASYNC =0 , +ABSYNC =1 +}; + +/* PaRAM slots are laid out like this */ +struct edma3_slot_layout { +u32 opt; +u32 src; +u32 a_b_cnt; +u32 dst; +u32 src_dst_bidx; +u32 link_bcntrld; +u32 src_dst_cidx; +u32 ccnt; +} __packed; + +/* +* Use this to assign trigger word number of edma3_slot_layout struct. +* trigger_word_name - is the exact name from edma3_slot_layout. +*/ +#define EDMA3_TWORD (trigger_word_name)\ + (offsetof(struct edma3_slot_layout, trigger_word_name) / 4) + +struct edma3_slot_config { +u32 opt; +u32 src; +u32 dst; +int bcnt; +int acnt; +int ccnt; +int src_bidx; +int dst_bidx; +int src_cidx; +int dst_cidx; +int bcntrld; +int link; +}; + +struct edma3_channel_config { +int slot; +int chnum; +int complete_code;/* indicate pending complete interrupt */ +int trigger_slot_word;/* only used for qedma */ +}; + +void qedma3_start (u32 base,struct edma3_channel_config *cfg); +void qedma3_stop (u32 base,struct edma3_channel_config *cfg); +void edma3_slot_configure (u32 base,int slot,struct edma3_slot_config *cfg); +int edma3_check_for_transfer (u32 base,struct edma3_channel_config *cfg); +void edma3_write_slot (u32 base,int slot,struct edma3_slot_layout *param); +void edma3_read_slot (u32 base,int slot,struct edma3_slot_layout *param); + +void edma3_set_dest (u32 base,int slot,u32 dst,enum edma3_address_mode mode, +enum edma3_fifo_width width); +void edma3_set_dest_index (u32 base,unsigned slot,int bidx,int cidx); +void edma3_set_dest_addr (u32 base,int slot,u32 dst); + +void edma3_set_src (u32 base,int slot,u32 src,enum edma3_address_mode mode, +enum edma3_fifo_width width); +void edma3_set_src_index (u32 base,unsigned slot,int bidx,int cidx); +void edma3_set_src_addr (u32 base,int slot,u32 src); + +void edma3_set_transfer_params (u32 base,int slot,int acnt, +int bcnt,int ccnt,u16 bcnt_rld, +enum edma3_sync_dimension sync_mode); + +#endif
drivers/dma/Makefile +1 -0
@@ -9,3 +9,4 @@ obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o obj-$(CONFIG_APBH_DMA) += apbh_dma.o obj-$(CONFIG_FSL_DMA) += fsl_dma.o obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o +obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
drivers/dma/ti-edma3.c new file +384 -0
384 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH v3 1/4 dma: ti-edma3: introduce edma3 driver
Quoted 12 lines · Ivan
The EDMA3 controller?s primary purpose is to service data transfers that you program between two memory-mapped slave endpoints on the device.
Typical usage includes, but is not limited to the following:
- Servicing software-driven paging transfers (e.g., transfers from external memory, such as SDRAM to internal device memory, such as DSP L2 SRAM)
- Servicing event-driven peripherals, such as a serial port
- Performing sorting or sub-frame extraction of various data structures
- Offloading data transfers from the main device DSP(s)
- See the device-specific data manual for specific peripherals that are accessible via the EDMA3 controller
Quoted 1 line
Signed-off-by Ivan Khoronzhuk <[email protected]>
Applied to u-boot-ti/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141023/fc4ed761/attachment.pgp>
PATCH v3 2/4 ARM: keystone: msmc: extend functionality of SES
In reply to Ivan KhoronzhukFrom: Vitaly Andrianov <[email protected]>
Add functions to set/get SES PMAX values of Pivilege ID pair. Also add msmc module definitions.
--- arch/arm/cpu/armv7/keystone/msmc.c | 26 +++++++++++++++++++++++++ arch/arm/include/asm/arch-keystone/hardware.h | 6 ++++++ arch/arm/include/asm/arch-keystone/msmc.h | 28 +++++++++++++++++++++++++++ 3 files changed, 60 insertions(+)
arch/arm/cpu/armv7/keystone/msmc.c +26 -0
@@ -66,3 +66,29 @@ void msmc_share_all_segments(int priv_id) msmc->ses[priv_id][j].mpaxh &=0xffffff7ful ; } } + +void msmc_map_ses_segment (int priv_id,int ses_pair, +u32 src_pfn,u32 dst_pfn,enum mpax_seg_size size) +{ +struct msms_regs *msmc = (struct msms_regs *)KS2_MSMC_CTRL_BASE ; + + msmc->ses[priv_id][ses_pair].mpaxh = src_pfn <<12 | + (size &0x1f ) |0x80 ; + msmc->ses[priv_id][ses_pair].mpaxl = dst_pfn <<8 |0x3f ; +} + +void msmc_get_ses_mpax (int priv_id,int ses_pair,u32 *mpax) +{ +struct msms_regs *msmc = (struct msms_regs *)KS2_MSMC_CTRL_BASE ; + + *mpax++ = msmc->ses[priv_id][ses_pair].mpaxl; + *mpax = msmc->ses[priv_id][ses_pair].mpaxh; +} + +void msmc_set_ses_mpax (int priv_id,int ses_pair,u32 *mpax) +{ +struct msms_regs *msmc = (struct msms_regs *)KS2_MSMC_CTRL_BASE ; + + msmc->ses[priv_id][ses_pair].mpaxl = *mpax++; + msmc->ses[priv_id][ses_pair].mpaxh = *mpax; +}
arch/arm/include/asm/arch-keystone/hardware.h +6 -0
@@ -148,6 +148,12 @@ typedef volatile unsigned int *dv_reg_p;#define KS2_MSMC_SEGMENT_QM_PDSP 10#define KS2_MSMC_SEGMENT_PCIE0 11 +/* MSMC segment size shift bits */ +#define KS2_MSMC_SEG_SIZE_SHIFT 12 +#define KS2_MSMC_MAP_SEG_NUM (2 << (30 - KS2_MSMC_SEG_SIZE_SHIFT)) +#define KS2_MSMC_DST_SEG_BASE (CONFIG_SYS_LPAE_SDRAM_BASE >> \ + KS2_MSMC_SEG_SIZE_SHIFT) +/* Device speed */ #define KS2_REV1_DEVSPEED (KS2_DEVICE_STATE_CTRL_BASE + 0xc98)#define KS2_EFUSE_BOOTROM (KS2_DEVICE_STATE_CTRL_BASE + 0xc90)
arch/arm/include/asm/arch-keystone/msmc.h +28 -0
@@ -12,6 +12,34 @@#include <asm/arch/hardware.h> +enum mpax_seg_size { +MPAX_SEG_4K =0x0b , +MPAX_SEG_8K , +MPAX_SEG_16K , +MPAX_SEG_32K , +MPAX_SEG_64K , +MPAX_SEG_128K , +MPAX_SEG_256K , +MPAX_SEG_512K , +MPAX_SEG_1M , +MPAX_SEG_2M , +MPAX_SEG_4M , +MPAX_SEG_8M , +MPAX_SEG_16M , +MPAX_SEG_32M , +MPAX_SEG_64M , +MPAX_SEG_128M , +MPAX_SEG_256M , +MPAX_SEG_512M , +MPAX_SEG_1G , +MPAX_SEG_2G , +MPAX_SEG_4G +}; +void msmc_share_all_segments (int priv_id); +void msmc_get_ses_mpax (int priv_id,int ses_pair,u32 *mpax); +void msmc_set_ses_mpax (int priv_id,int ses_pair,u32 *mpax); +void msmc_map_ses_segment (int priv_id,int ses_pair, +u32 src_pfn,u32 dst_pfn,enum mpax_seg_size size);#endif
Signature · 1 line
1.8.3.2
PATCH v3 2/4 ARM: keystone: msmc: extend functionality of SES
Quoted 9 lines · Ivan
From: Vitaly Andrianov <[email protected]>
Add functions to set/get SES PMAX values of Pivilege ID pair. Also add msmc module definitions.
Acked-by Murali Karicheri <[email protected]>Signed-off-by Hao Zhang <[email protected]>Signed-off-by Vitaly Andrianov <[email protected]>Signed-off-by Ivan Khoronzhuk <[email protected]>
Applied to u-boot-ti/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141023/79d694ae/attachment.pgp>
PATCH v3 3/4 keystone2: ecc: add ddr3 error detection and correction support
In reply to Ivan KhoronzhukFrom: Vitaly Andrianov <[email protected]>
This patch adds the DDR3 ECC support to enable ECC in the DDR3 EMIF controller for Keystone II devices.
By default, ECC will only be enabled if RMW is supported in the DDR EMIF controller. The entire DDR memory will be scrubbed to zero using an EDMA channel after ECC is enabled and before u-boot is re-located to DDR memory.
An ecc_test environment variable is added for ECC testing. If ecc_test is set to 0, a detection of 2-bit error will reset the device, if ecc_test is set to 1, 2-bit error detection will not reset the device, user can still boot the kernel to check the ECC error handling in kernel.
--- arch/arm/cpu/armv7/keystone/ddr3.c | 244 +++++++++++++++++++++ arch/arm/include/asm/arch-keystone/ddr3.h | 6 + arch/arm/include/asm/arch-keystone/hardware-k2hk.h | 4 + arch/arm/include/asm/arch-keystone/hardware.h | 46 ++++ board/ti/ks2_evm/board.c | 3 + board/ti/ks2_evm/ddr3_k2hk.c | 16 ++ 6 files changed, 319 insertions(+)
arch/arm/cpu/armv7/keystone/ddr3.c +244 -0
@@ -9,9 +9,19 @@#include <asm/io.h> #include <common.h> +#include <asm/arch/msmc.h> #include <asm/arch/ddr3.h> #include <asm/arch/psc_defs.h> +#include <asm/ti-common/ti-edma3.h> + +#define DDR3_EDMA_BLK_SIZE_SHIFT 10 +#define DDR3_EDMA_BLK_SIZE (1 << DDR3_EDMA_BLK_SIZE_SHIFT) +#define DDR3_EDMA_BCNT 0x8000 +#define DDR3_EDMA_CCNT 1 +#define DDR3_EDMA_XF_SIZE (DDR3_EDMA_BLK_SIZE * DDR3_EDMA_BCNT) +#define DDR3_EDMA_SLOT_NUM 1 +void ddr3_init_ddrphy (u32 base,struct ddr3_phy_config *phy_cfg) {unsigned int tmp;
@@ -70,6 +80,240 @@ void ddr3_init_ddremif(u32 base, struct ddr3_emif_config *emif_cfg)__raw_writel (emif_cfg->sdrfc, base +KS2_DDR3_SDRFC_OFFSET ); } +int ddr3_ecc_support_rmw (u32 base) +{ +u32 value =__raw_readl (base +KS2_DDR3_MIDR_OFFSET ); + +/* Check the DDR3 controller ID reg if the controllers +supports ECC RMW or not */ +if (value ==0x40461C02 ) +return 1 ; + +return 0 ; +} + +static void ddr3_ecc_config (u32 base,u32 value) +{ +u32 data; + +__raw_writel (value, base +KS2_DDR3_ECC_CTRL_OFFSET ); +udelay (100000 );/* delay required to synchronize across clock domains */ + +if (value &KS2_DDR3_ECC_EN ) { +/* Clear the 1-bit error count */ + data =__raw_readl (base +KS2_DDR3_ONE_BIT_ECC_ERR_CNT_OFFSET ); +__raw_writel (data, base +KS2_DDR3_ONE_BIT_ECC_ERR_CNT_OFFSET ); + +/* enable the ECC interrupt */ +__raw_writel (KS2_DDR3_1B_ECC_ERR_SYS |KS2_DDR3_2B_ECC_ERR_SYS | +KS2_DDR3_WR_ECC_ERR_SYS , + base +KS2_DDR3_ECC_INT_ENABLE_SET_SYS_OFFSET ); + +/* Clear the ECC error interrupt status */ +__raw_writel (KS2_DDR3_1B_ECC_ERR_SYS |KS2_DDR3_2B_ECC_ERR_SYS | +KS2_DDR3_WR_ECC_ERR_SYS , + base +KS2_DDR3_ECC_INT_STATUS_OFFSET ); + } +} + +static void ddr3_reset_data (u32 base,u32 ddr3_size) +{ +u32 mpax[2 ]; +u32 seg_num; +u32 seg, blks, dst, edma_blks; +struct edma3_slot_config slot; +struct edma3_channel_config edma_channel; +u32 edma_src[DDR3_EDMA_BLK_SIZE /4 ]__aligned(16) = {0 , }; + +/* Setup an edma to copy the 1k block to the entire DDR */ +puts ("\nClear entire DDR3 memory to enable ECC\n" ); + +/* save the SES MPAX regs */ +msmc_get_ses_mpax (8 ,0 , mpax); + +/* setup edma slot 1 configuration */ + slot.opt =EDMA3_SLOPT_TRANS_COMP_INT_ENB | +EDMA3_SLOPT_COMP_CODE (0 ) | +EDMA3_SLOPT_STATIC |EDMA3_SLOPT_AB_SYNC ; + slot.bcnt =DDR3_EDMA_BCNT ; + slot.acnt =DDR3_EDMA_BLK_SIZE ; + slot.ccnt =DDR3_EDMA_CCNT ; + slot.src_bidx =0 ; + slot.dst_bidx =DDR3_EDMA_BLK_SIZE ; + slot.src_cidx =0 ; + slot.dst_cidx =0 ; + slot.link =EDMA3_PARSET_NULL_LINK ; + slot.bcntrld =0 ; +edma3_slot_configure (KS2_EDMA0_BASE ,DDR3_EDMA_SLOT_NUM , &slot); + +/* configure quik edma channel */ + edma_channel.slot =DDR3_EDMA_SLOT_NUM ; + edma_channel.chnum =0 ; + edma_channel.complete_code =0 ; +/* event trigger after dst update */ + edma_channel.trigger_slot_word =EDMA3_TWORD (dst); +qedma3_start (KS2_EDMA0_BASE , &edma_channel); + +/* DDR3 size in segments (4KB seg size) */ + seg_num = ddr3_size << (30 -KS2_MSMC_SEG_SIZE_SHIFT ); + +for (seg =0 ; seg < seg_num; seg +=KS2_MSMC_MAP_SEG_NUM ) { +/* map 2GB 36-bit DDR address to 32-bit DDR address in EMIF +access slave interface so that edma driver can access */ +msmc_map_ses_segment (8 ,0 , base >>KS2_MSMC_SEG_SIZE_SHIFT , +KS2_MSMC_DST_SEG_BASE + seg,MPAX_SEG_2G ); + +if ((seg_num - seg) >KS2_MSMC_MAP_SEG_NUM ) + edma_blks =KS2_MSMC_MAP_SEG_NUM << + (KS2_MSMC_SEG_SIZE_SHIFT + -DDR3_EDMA_BLK_SIZE_SHIFT ); +else + edma_blks = (seg_num - seg) << (KS2_MSMC_SEG_SIZE_SHIFT + -DDR3_EDMA_BLK_SIZE_SHIFT ); + +/* Use edma driver to scrub 2GB DDR memory */ +for (dst = base, blks =0 ; blks < edma_blks; + blks +=DDR3_EDMA_BCNT , dst +=DDR3_EDMA_XF_SIZE ) { +edma3_set_src_addr (KS2_EDMA0_BASE , + edma_channel.slot, (u32 )edma_src); +edma3_set_dest_addr (KS2_EDMA0_BASE , + edma_channel.slot, (u32 )dst); + +while (edma3_check_for_transfer (KS2_EDMA0_BASE , + &edma_channel)) +udelay (10 ); + } + } + +qedma3_stop (KS2_EDMA0_BASE , &edma_channel); + +/* restore the SES MPAX regs */ +msmc_set_ses_mpax (8 ,0 , mpax); +} + +static void ddr3_ecc_init_range (u32 base) +{ +u32 ecc_val =KS2_DDR3_ECC_EN ; +u32 rmw =ddr3_ecc_support_rmw (base); + +if (rmw) + ecc_val |=KS2_DDR3_ECC_RMW_EN ; + +__raw_writel (0 , base +KS2_DDR3_ECC_ADDR_RANGE1_OFFSET ); + +ddr3_ecc_config (base, ecc_val); +} + +void ddr3_enable_ecc (u32 base,int test) +{ +u32 ecc_val =KS2_DDR3_ECC_ENABLE ; +u32 rmw =ddr3_ecc_support_rmw (base); + +if (test) + ecc_val |=KS2_DDR3_ECC_ADDR_RNG_1_EN ; + +if (!rmw) { +if (!test) +/* by default, disable ecc when rmw = 0 and no +ecc test */ + ecc_val =0 ; + }else { + ecc_val |=KS2_DDR3_ECC_RMW_EN ; + } + +ddr3_ecc_config (base, ecc_val); +} + +void ddr3_disable_ecc (u32 base) +{ +ddr3_ecc_config (base,0 ); +} + +#if defined(CONFIG_SOC_K2HK ) || defined(CONFIG_SOC_K2L ) +static void cic_init (u32 base) +{ +/* Disable CIC global interrupts */ +__raw_writel (0 , base +KS2_CIC_GLOBAL_ENABLE ); + +/* Set to normal mode, no nesting, no priority hold */ +__raw_writel (0 , base +KS2_CIC_CTRL ); +__raw_writel (0 , base +KS2_CIC_HOST_CTRL ); + +/* Enable CIC global interrupts */ +__raw_writel (1 , base +KS2_CIC_GLOBAL_ENABLE ); +} + +static void cic_map_cic_to_gic (u32 base,u32 chan_num,u32 irq_num) +{ +/* Map the system interrupt to a CIC channel */ +__raw_writeb (chan_num, base +KS2_CIC_CHAN_MAP (0 ) + irq_num); + +/* Enable CIC system interrupt */ +__raw_writel (irq_num, base +KS2_CIC_SYS_ENABLE_IDX_SET ); + +/* Enable CIC Host interrupt */ +__raw_writel (chan_num, base +KS2_CIC_HOST_ENABLE_IDX_SET ); +} + +static void ddr3_map_ecc_cic2_irq (u32 base) +{ +cic_init (base); +cic_map_cic_to_gic (base,KS2_CIC2_DDR3_ECC_CHAN_NUM , +KS2_CIC2_DDR3_ECC_IRQ_NUM ); +} +#endif + +void ddr3_init_ecc (u32 base) +{ +u32 ddr3_size; + +if (!ddr3_ecc_support_rmw (base)) { +ddr3_disable_ecc (base); +return ; + } + +ddr3_ecc_init_range (base); + ddr3_size =ddr3_get_size (); +ddr3_reset_data (CONFIG_SYS_SDRAM_BASE , ddr3_size); + +/* mapping DDR3 ECC system interrupt from CIC2 to GIC */ +#if defined(CONFIG_SOC_K2HK ) || defined(CONFIG_SOC_K2L ) +ddr3_map_ecc_cic2_irq (KS2_CIC2_BASE ); +#endif +ddr3_enable_ecc (base,0 ); +} + +void ddr3_check_ecc_int (u32 base) +{ +char *env; +int ecc_test =0 ; +u32 value =__raw_readl (base +KS2_DDR3_ECC_INT_STATUS_OFFSET ); + + env =getenv ("ecc_test" ); +if (env) + ecc_test =simple_strtol (env,NULL ,0 ); + +if (value &KS2_DDR3_WR_ECC_ERR_SYS ) +puts ("DDR3 ECC write error interrupted\n" ); + +if (value &KS2_DDR3_2B_ECC_ERR_SYS ) { +puts ("DDR3 ECC 2-bit error interrupted\n" ); + +if (!ecc_test) { +puts ("Reseting the device ...\n" ); +reset_cpu (0 ); + } + } + + value =__raw_readl (base +KS2_DDR3_ONE_BIT_ECC_ERR_CNT_OFFSET ); +if (value) { +printf ("1-bit ECC err count: 0x%x\n" , value); + value =__raw_readl (base + +KS2_DDR3_ONE_BIT_ECC_ERR_ADDR_LOG_OFFSET ); +printf ("1-bit ECC err address log: 0x%x\n" , value); + } +} +void ddr3_reset_ddrphy (void ) {u32 tmp;
arch/arm/include/asm/arch-keystone/ddr3.h +6 -0
@@ -49,8 +49,14 @@ struct ddr3_emif_config { };void ddr3_init (void ); +int ddr3_get_size (void );void ddr3_reset_ddrphy (void ); +void ddr3_init_ecc (u32 base); +void ddr3_disable_ecc (u32 base); +void ddr3_check_ecc_int (u32 base); +int ddr3_ecc_support_rmw (u32 base);void ddr3_err_reset_workaround (void ); +void ddr3_enable_ecc (u32 base,int test);void ddr3_init_ddrphy (u32 base,struct ddr3_phy_config *phy_cfg);void ddr3_init_ddremif (u32 base,struct ddr3_emif_config *emif_cfg);
arch/arm/include/asm/arch-keystone/hardware-k2hk.h +4 -0
@@ -79,6 +79,10 @@#define KS2_DDR3B_EMIF_DATA_BASE 0x60000000#define KS2_DDR3B_DDRPHYC 0x02328000 +#define KS2_CIC2_DDR3_ECC_IRQ_NUM 0x0D3/* DDR3 ECC system irq number */ +#define KS2_CIC2_DDR3_ECC_CHAN_NUM 0x01D/* DDR3 ECC int mapped to CIC2 +channel 29 */ +/* SGMII SerDes */ #define KS2_LANES_PER_SGMII_SERDES 4
arch/arm/include/asm/arch-keystone/hardware.h +46 -0
52 lines not on this page · raw message
board/ti/ks2_evm/board.c +3 -0
@@ -40,6 +40,7 @@ int dram_init(void) gd->ram_size =get_ram_size ((long *)CONFIG_SYS_SDRAM_BASE ,CONFIG_MAX_RAM_BANK_SIZE );aemif_init (ARRAY_SIZE (aemif_configs), aemif_configs); +ddr3_init_ecc (KS2_DDR3A_EMIF_CTRL_BASE );return 0 ; }
@@ -254,5 +255,7 @@ void ft_board_setup_ex(void *blob, bd_t *bd) reserve_start += 2; } } + +ddr3_check_ecc_int (KS2_DDR3A_EMIF_CTRL_BASE ); }#endif
board/ti/ks2_evm/ddr3_k2hk.c +16 -0
@@ -12,6 +12,8 @@#include <asm/arch/ddr3.h> #include <asm/arch/hardware.h> +static int ddr3_size; +struct pll_init_data ddr3a_333 =DDR3_PLL_333 (A );struct pll_init_data ddr3a_400 =DDR3_PLL_400 (A );
@@ -44,12 +46,14 @@ void ddr3_init(void)ddr3_init_ddremif (KS2_DDR3A_EMIF_CTRL_BASE , &ddr3_1600_8g);printf ("DRAM: Capacity 8 GiB (includes reported below)\n" ); + ddr3_size =8 ; }else {ddr3_init_ddrphy (KS2_DDR3A_DDRPHYC , &ddr3phy_1600_8g); ddr3_1600_8g.sdcfg |=0x1000 ;ddr3_init_ddremif (KS2_DDR3A_EMIF_CTRL_BASE , &ddr3_1600_8g);printf ("DRAM: Capacity 4 GiB (includes reported below)\n" ); + ddr3_size =4 ; } }else if (!strcmp (dimm_name,"SQR-SD3T-2G1333SED" )) {init_pll (&ddr3a_333);
@@ -70,11 +74,15 @@ void ddr3_init(void) }ddr3_init_ddremif (KS2_DDR3A_EMIF_CTRL_BASE , &ddr3_1333_2g); + ddr3_size =2 ; +printf ("DRAM: 2 GiB" ); }else {ddr3_init_ddrphy (KS2_DDR3A_DDRPHYC , &ddr3phy_1333_2g); ddr3_1333_2g.sdcfg |=0x1000 ;ddr3_init_ddremif (KS2_DDR3A_EMIF_CTRL_BASE , &ddr3_1333_2g); + ddr3_size =1 ; +printf ("DRAM: 1 GiB" ); } }else {printf ("Unknown SO-DIMM. Cannot configure DDR3\n" );
@@ -86,3 +94,11 @@ void ddr3_init(void)if (cpu_revision () <=1 )ddr3_err_reset_workaround (); } + +/** +* ddr3_get_size - return ddr3 size in GiB +*/ +int ddr3_get_size (void ) +{ +return ddr3_size; +}
Signature · 1 line
1.8.3.2
PATCH v3 3/4 keystone2: ecc: add ddr3 error detection and correction support
Quoted 16 lines · Ivan
From: Vitaly Andrianov <[email protected]>
This patch adds the DDR3 ECC support to enable ECC in the DDR3 EMIF controller for Keystone II devices.
By default, ECC will only be enabled if RMW is supported in the DDR EMIF controller. The entire DDR memory will be scrubbed to zero using an EDMA channel after ECC is enabled and before u-boot is re-located to DDR memory.
An
ecc_testenvironment variable is added for ECC testing. Ifecc_testis set to 0, a detection of 2-bit error will reset the device, ifecc_testis set to 1, 2-bit error detection will not reset the device, user can still boot the kernel to check the ECC error handling in kernel.
Quoted 3 lines
Signed-off-by Hao Zhang <[email protected]>Signed-off-by Vitaly Andrianov <[email protected]>Signed-off-by Ivan Khoronzhuk <[email protected]>
Applied to u-boot-ti/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141023/8ff86cbb/attachment.pgp>
PATCH v3 4/4 ARM: keystone: cmd_ddr3: add ddr3 commands to test ddr
In reply to Ivan KhoronzhukFrom: Hao Zhang <[email protected]>
Add ddr3 commands:
test <start_addr in hex> <end_addr in hex> - test DDR from start\n
address to end address\n
ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n
compare DDR data of (size) bytes from start address to end address\n
ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n
in DDR data at <addr>, the command will read a 32-bit data\n from <addr>, and write (data ^ bit_err) back to <addr>\n
Delete CONFIG_MAX_UBOOT_MEM_SIZE, as it was supposed to be used for ddr3 commands and for now it's not needed any more.
--- arch/arm/cpu/armv7/keystone/Makefile | 2 +- arch/arm/cpu/armv7/keystone/cmd_ddr3.c | 248 +++++++++++++++++++++++++++++++++ include/configs/ks2_evm.h | 4 - 3 files changed, 249 insertions(+), 5 deletions(-) create mode 100644 arch/arm/cpu/armv7/keystone/cmd_ddr3.c
arch/arm/cpu/armv7/keystone/Makefile +1 -1
@@ -14,5 +14,5 @@ obj-$(CONFIG_SOC_K2L) += clock-k2l.o obj-y += cmd_clock.o obj-y += cmd_mon.o obj-y += msmc.o -obj-y += ddr3.o +obj-y += ddr3.o cmd_ddr3.o obj-y += keystone.o
arch/arm/cpu/armv7/keystone/cmd_ddr3.c new file +248 -0
248 lines not on this page · raw message
include/configs/ks2_evm.h +0 -4
@@ -321,8 +321,4 @@#include <asm/arch/clock.h> #define CONFIG_SYS_HZ_CLOCK clk_get_rate(KS2_CLK1_6) -/* Maximum memory size for relocated U-boot at the end of the DDR3 memory -which is NOT applicable for DDR ECC test */ -#define CONFIG_MAX_UBOOT_MEM_SIZE (4 << 20)/* 4 MiB */ -#endif /* __CONFIG_KS2_EVM_H */
Signature · 1 line
1.8.3.2
PATCH v3 4/4 ARM: keystone: cmd_ddr3: add ddr3 commands to test ddr
Quoted 13 lines · Ivan
From: Hao Zhang <[email protected]>
Add ddr3 commands:
test <
start_addrin hex> <end_addrin hex> - test DDR from start\n
address to end address\n
ddr compare <start_addrin hex> <end_addrin hex> <size in hex> -\n
compare DDR data of (size) bytes from start address to end address\n
ddrecc_err<addr in hex> <bit_errin hex> - generate bit errors\n
in DDR data at <addr>, the command will read a 32-bit data\n from <addr>, and write (data ^bit_err) back to <addr>\n
Quoted 5 lines
Delete
CONFIG_MAX_UBOOT_MEM_SIZE, as it was supposed to be used for ddr3 commands and for now it's not needed any more.Signed-off-by Hao Zhang <[email protected]>Signed-off-by Ivan Khoronzhuk <[email protected]>
Applied to u-boot-ti/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141023/1e9b810d/attachment.pgp>