From patchwork Tue Aug 11 15:08:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Roese X-Patchwork-Id: 506125 X-Patchwork-Delegate: sr@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 9E40F14056B for ; Wed, 12 Aug 2015 01:08:25 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B0FB04B99C; Tue, 11 Aug 2015 17:08:20 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9x5ErLcYVhs0; Tue, 11 Aug 2015 17:08:20 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 85D6E4BC03; Tue, 11 Aug 2015 17:08:15 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BF5CD4BBC8 for ; Tue, 11 Aug 2015 17:08:10 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aTzRSr8Foizm for ; Tue, 11 Aug 2015 17:08:10 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mo4-p04-ob.smtp.rzone.de (mo4-p04-ob.smtp.rzone.de [81.169.146.178]) by theia.denx.de (Postfix) with ESMTPS id 8A1164B958 for ; Tue, 11 Aug 2015 17:08:06 +0200 (CEST) X-RZG-CLASS-ID: mo04 X-RZG-AUTH: :IW0NeWC7b/q2i6W/qstXb1SBUuFnrGohfvxEndrDXKjzPMsB3oimjD61I4fPQhgcxmkf7w== Received: from stefan-work.domain_not_set.invalid (b9168f91.cgn.dg-w.de [185.22.143.145]) by post.strato.de (RZmta 37.8 SBL|AUTH) with ESMTPA id 3051far7BF86YTG; Tue, 11 Aug 2015 17:08:06 +0200 (CEST) From: Stefan Roese To: u-boot@lists.denx.de Date: Tue, 11 Aug 2015 17:08:05 +0200 Message-Id: <1439305685-28517-5-git-send-email-sr@denx.de> X-Mailer: git-send-email 2.4.8 In-Reply-To: <1439305685-28517-1-git-send-email-sr@denx.de> References: <1439305685-28517-1-git-send-email-sr@denx.de> Cc: Luka Perkov Subject: [U-Boot] [PATCH 5/5] arm: mvebu: Add complete SDRAM ECC scrubbing X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch introduces the SDRAM scrubbing for ECC enabled board to fill/initialize the ECC bytes. This is done via the XOR engine to speed up the process. The scrubbing is a 2-stage process: 1) SPL scrubs the area 0 - 0x100.0000 (16MiB) for the main U-Boot 2) U-Boot scrubs the remaining SDRAM area(s) Signed-off-by: Stefan Roese Cc: Luka Perkov --- arch/arm/mach-mvebu/Makefile | 4 ++ arch/arm/mach-mvebu/dram.c | 130 ++++++++++++++++++++++++++++++++++++++++-- drivers/ddr/marvell/axp/xor.c | 3 +- drivers/ddr/marvell/axp/xor.h | 1 + 4 files changed, 130 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 446ce04..21c56a4 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -14,6 +14,10 @@ else obj-y = cpu.o obj-y += dram.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += ../../../drivers/ddr/marvell/a38x/xor.o +obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += ../../../drivers/ddr/marvell/axp/xor.o +endif obj-y += gpio.o obj-y += mbus.o obj-y += timer.o diff --git a/arch/arm/mach-mvebu/dram.c b/arch/arm/mach-mvebu/dram.c index a75ada3..1daffce 100644 --- a/arch/arm/mach-mvebu/dram.c +++ b/arch/arm/mach-mvebu/dram.c @@ -13,10 +13,12 @@ #include #ifdef CONFIG_SYS_MVEBU_DDR_A38X -#include "../../../drivers/ddr/marvell/a38x/ddr3_init.h" +#include "../../../drivers/ddr/marvell/axp/xor.h" +#include "../../../drivers/ddr/marvell/axp/xor_regs.h" #endif #ifdef CONFIG_SYS_MVEBU_DDR_AXP -#include "../../../drivers/ddr/marvell/axp/ddr3_init.h" +#include "../../../drivers/ddr/marvell/axp/xor.h" +#include "../../../drivers/ddr/marvell/axp/xor_regs.h" #endif DECLARE_GLOBAL_DATA_PTR; @@ -37,6 +39,18 @@ struct sdram_addr_dec { #define SDRAM_SIZE_MAX 0xc0000000 +#define SCRUB_MAGIC 0xbeefdead + +#define SCRB_XOR_UNIT 0 +#define SCRB_XOR_CHAN 1 +#define SCRB_XOR_WIN 0 + +#define XEBARX_BASE_OFFS 16 + +static u32 xor_ctrl_save; +static u32 xor_base_save; +static u32 xor_mask_save; + /* * mvebu_sdram_bar - reads SDRAM Base Address Register */ @@ -102,6 +116,109 @@ void mvebu_sdram_size_adjust(enum memory_bank bank) mvebu_sdram_bs_set(bank, size); } +static void mv_xor_init2(u32 cs) +{ + u32 reg, base, size, base2; + u32 bank_attr[4] = { 0xe00, 0xd00, 0xb00, 0x700 }; + + xor_ctrl_save = reg_read(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT, + SCRB_XOR_CHAN)); + xor_base_save = reg_read(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT, + SCRB_XOR_WIN)); + xor_mask_save = reg_read(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT, + SCRB_XOR_WIN)); + + /* Enable Window x for each CS */ + reg = 0x1; + reg |= (0x3 << 16); + reg_write(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT, SCRB_XOR_CHAN), reg); + + base = 0; + size = mvebu_sdram_bs(cs) - 1; + if (size) { + base2 = ((base / (64 << 10)) << XEBARX_BASE_OFFS) | + bank_attr[cs]; + reg_write(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN), + base2); + + base += size + 1; + size = (size / (64 << 10)) << 16; + /* Window x - size - 256 MB */ + reg_write(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN), size); + } + + mv_xor_hal_init(0); + + return; +} + +static void mv_xor_finish2(void) +{ + reg_write(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT, SCRB_XOR_CHAN), + xor_ctrl_save); + reg_write(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN), + xor_base_save); + reg_write(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN), + xor_mask_save); +} + +static void dram_ecc_scrubbing(void) +{ + int cs; + u32 size, temp; + u32 total_mem = 0; + u64 total; + u32 start_addr; + + /* + * The DDR training code from the bin_hdr / SPL already + * scrubbed the DDR till 0x1000000. And the main U-Boot + * is loaded to an address < 0x1000000. So we need to + * skip this range to not re-scrub this area again. + */ + temp = reg_read(REG_SDRAM_CONFIG_ADDR); + temp |= (1 << REG_SDRAM_CONFIG_IERR_OFFS); + reg_write(REG_SDRAM_CONFIG_ADDR, temp); + + for (cs = 0; cs < CONFIG_NR_DRAM_BANKS; cs++) { + size = mvebu_sdram_bs(cs) - 1; + if (size == 0) + continue; + + total = (u64)size + 1; + total_mem += (u32)(total / (1 << 30)); + start_addr = 0; + mv_xor_init2(cs); + + /* Skip first 16 MiB */ + if (0 == cs) { + start_addr = 0x1000000; + size -= start_addr; + } + + mv_xor_mem_init(SCRB_XOR_CHAN, start_addr, size, + SCRUB_MAGIC, SCRUB_MAGIC); + + /* Wait for previous transfer completion */ + while (mv_xor_state_get(SCRB_XOR_CHAN) != MV_IDLE) + ; + + mv_xor_finish2(); + } + + temp = reg_read(REG_SDRAM_CONFIG_ADDR); + temp &= ~(1 << REG_SDRAM_CONFIG_IERR_OFFS); + reg_write(REG_SDRAM_CONFIG_ADDR, temp); +} + +static int ecc_enabled(void) +{ + if (reg_read(REG_SDRAM_CONFIG_ADDR) & (1 << REG_SDRAM_CONFIG_ECC_OFFS)) + return 1; + + return 0; +} + int dram_init(void) { u64 size = 0; @@ -135,6 +252,10 @@ int dram_init(void) gd->bd->bi_dram[i].size = 0; } + + if (ecc_enabled()) + dram_ecc_scrubbing(); + gd->ram_size = size; return 0; @@ -162,10 +283,7 @@ void dram_init_banksize(void) void board_add_ram_info(int use_default) { - u32 reg; - - reg = reg_read(REG_SDRAM_CONFIG_ADDR); - if (reg & (1 << REG_SDRAM_CONFIG_ECC_OFFS)) + if (ecc_enabled()) printf(" (ECC"); else printf(" (ECC not"); diff --git a/drivers/ddr/marvell/axp/xor.c b/drivers/ddr/marvell/axp/xor.c index 66c96ae..54924ca 100644 --- a/drivers/ddr/marvell/axp/xor.c +++ b/drivers/ddr/marvell/axp/xor.c @@ -18,7 +18,6 @@ static u32 xor_regs_ctrl_backup; static u32 xor_regs_base_backup[MAX_CS]; static u32 xor_regs_mask_backup[MAX_CS]; -static void mv_xor_hal_init(u32 chan_num); static int mv_xor_cmd_set(u32 chan, int command); static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl); @@ -110,7 +109,7 @@ void mv_sys_xor_finish(void) * RETURN: * MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. */ -static void mv_xor_hal_init(u32 chan_num) +void mv_xor_hal_init(u32 chan_num) { u32 i; diff --git a/drivers/ddr/marvell/axp/xor.h b/drivers/ddr/marvell/axp/xor.h index 3536487..3ff784d 100644 --- a/drivers/ddr/marvell/axp/xor.h +++ b/drivers/ddr/marvell/axp/xor.h @@ -60,6 +60,7 @@ struct crc_dma_desc { u32 src_addr1; /* Mode: Source Block address pointer */ } __packed; +void mv_xor_hal_init(u32 chan_num); int mv_xor_state_get(u32 chan); void mv_sys_xor_init(MV_DRAM_INFO *dram_info); void mv_sys_xor_finish(void);