From patchwork Mon Sep 2 12:15:05 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajeshwari Shinde X-Patchwork-Id: 19678 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-gh0-f199.google.com (mail-gh0-f199.google.com [209.85.160.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D2D9C248D9 for ; Mon, 2 Sep 2013 12:13:48 +0000 (UTC) Received: by mail-gh0-f199.google.com with SMTP id g14sf4727333ghb.10 for ; Mon, 02 Sep 2013 05:13:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=mime-version:x-gm-message-state:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:dlp-filter:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=RbsFf0JRqkO6xiIpxG49j0ccKyxXLbrzGOwMgu+AN6s=; b=TRRLmbT5hpIngPqNNhmbdW0ef8j1RfnZZm1bvv55zpXvmxHirdnY/14PSyKT997Uru 3zZZDokCIHz2nvk9NlzoyfATuXNBRvHnaReSJlo06zJmtmvdZYdCRqb52GJhGqH4DQ39 VeV5M17dt3xxQN+Kr7LsrV8aHgMDYO76Ia8eOdcPVKPyxDaXsLP3D8r8gniEI5crCKpZ 732upKacZ97CfFXEppA+EinZQ9zo9nhvnv7iB5QzIZY5qV2YETY4FhlfMWWUwf/UHmiv KqFHVF4hiR5e2J5i2Qm2++MGtfcN/117iwNEF211JXSVnCsPj7cP1IM4IODsIES26tt/ sPOw== X-Received: by 10.236.63.165 with SMTP id a25mr8167332yhd.43.1378124028399; Mon, 02 Sep 2013 05:13:48 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.104.111 with SMTP id gd15ls670549qeb.68.gmail; Mon, 02 Sep 2013 05:13:48 -0700 (PDT) X-Received: by 10.52.34.40 with SMTP id w8mr18684732vdi.7.1378124028266; Mon, 02 Sep 2013 05:13:48 -0700 (PDT) Received: from mail-ve0-f180.google.com (mail-ve0-f180.google.com [209.85.128.180]) by mx.google.com with ESMTPS id wp10si2665609vdb.6.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 02 Sep 2013 05:13:48 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.180; Received: by mail-ve0-f180.google.com with SMTP id pb11so3115760veb.11 for ; Mon, 02 Sep 2013 05:13:48 -0700 (PDT) X-Gm-Message-State: ALoCoQnaLpSN95U13aCtXtT0YPzRFeefA46UsrjRoMMypPW+Xycj5Xu0Eko8unFveWg+NboCCLA1 X-Received: by 10.52.103.101 with SMTP id fv5mr238051vdb.31.1378124028071; Mon, 02 Sep 2013 05:13:48 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp111869vcz; Mon, 2 Sep 2013 05:13:47 -0700 (PDT) X-Received: by 10.66.102.1 with SMTP id fk1mr26242996pab.90.1378124026907; Mon, 02 Sep 2013 05:13:46 -0700 (PDT) Received: from mailout3.samsung.com (mailout3.samsung.com. [203.254.224.33]) by mx.google.com with ESMTP id co1si10612971pbc.18.1969.12.31.16.00.00; Mon, 02 Sep 2013 05:13:46 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of rajeshwari.s@samsung.com designates 203.254.224.33 as permitted sender) client-ip=203.254.224.33; Received: from epcpsbgr5.samsung.com (u145.gpu120.samsung.co.kr [203.254.230.145]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MSH00CVAZA5N5X0@mailout3.samsung.com>; Mon, 02 Sep 2013 21:13:35 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.122]) by epcpsbgr5.samsung.com (EPCPMTA) with SMTP id 20.7A.29948.EE084225; Mon, 02 Sep 2013 21:13:35 +0900 (KST) X-AuditID: cbfee691-b7f4a6d0000074fc-87-522480ee8910 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 28.50.09055.EE084225; Mon, 02 Sep 2013 21:13:34 +0900 (KST) Received: from localhost.localdomain.com ([107.108.73.95]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MSH004D4ZABZW60@mmp2.samsung.com>; Mon, 02 Sep 2013 21:13:34 +0900 (KST) From: Rajeshwari S Shinde To: u-boot@lists.denx.de Cc: patches@linaro.org, sjg@chromium.org, mk7.kang@samsung.com, chander.kashyap@linaro.org, u-boot-review@google.com, Akshay Saraswat Subject: [PATCH 04/10] Exynos5420: Add DDR3 initialization for 5420 Date: Mon, 02 Sep 2013 17:45:05 +0530 Message-id: <1378124111-26145-5-git-send-email-rajeshwari.s@samsung.com> X-Mailer: git-send-email 1.7.11.7 In-reply-to: <1378124111-26145-1-git-send-email-rajeshwari.s@samsung.com> References: <1378124111-26145-1-git-send-email-rajeshwari.s@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrOLMWRmVeSWpSXmKPExsWyRsSkSvd9g0qQwa4oi1N/HjNaPFx/k8Wi 40gLo8WUw19YLL5t2cZosfz1RnaLt3s72R3YPWY3XGTxWLCp1OPOtT1sHmfv7GD06NuyijGA NYrLJiU1J7MstUjfLoEro/XBaZaCJRsYK7ZsaWdqYFwwkbGLkZNDQsBEYsruPmYIW0ziwr31 bF2MXBxCAksZJZ7sucsOU7RlbzszRGI6o8TBhU+gqrqYJL5dfMLUxcjBwQZUtfFEAkiDiICE xK/+q2AbmAUWMEpM6AcbJCzgLDFx9xwWEJtFQFVi2fs9bCA2r4CHRMObVVBXKErMWPIMrJdT wFPi+5xtYLYQUM2ao3sYQfZKCMxjl9h+6wcjxCABiW+TD7GA3CAhICux6QDUHEmJgytusExg FF7AyLCKUTS1ILmgOCm9yFSvODG3uDQvXS85P3cTIzDQT/97NnEH4/0D1ocYk4HGTWSWEk3O B0ZKXkm8obGZkYWpiamxkbmlGWnCSuK86i3WgUIC6YklqdmpqQWpRfFFpTmpxYcYmTg4pRoY Mx0mHQ5fYKSyQfBm4ZKco79cvny8ml+171yX1tfT5aqsbr/l0+V0z92cGKBXX164dNr8j0f3 8tQxp/Zwt8aflxVvnFcd1O74N3mNPpvprnMBgntVf97bqnaVs3+HoYn7rYsb91ppcKafjNl7 /ur8Kdqu0xPFLK1MCp6H7rCP/n1WW+th0473SizFGYmGWsxFxYkAHc+eYooCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrKIsWRmVeSWpSXmKPExsVy+t9jQd13DSpBBl/v61uc+vOY0eLh+pss Fh1HWhgtphz+wmLxbcs2RovlrzeyW7zd28nuwO4xu+Eii8eCTaUed67tYfM4e2cHo0ffllWM AaxRDYw2GamJKalFCql5yfkpmXnptkrewfHO8aZmBoa6hpYW5koKeYm5qbZKLj4Bum6ZOUB3 KCmUJeaUAoUCEouLlfTtME0IDXHTtYBpjND1DQmC6zEyQAMJaxgzWh+cZilYsoGxYsuWdqYG xgUTGbsYOTkkBEwktuxtZ4awxSQu3FvP1sXIxSEkMJ1R4uDCJ1BOF5PEt4tPmLoYOTjYgDo2 nkgAaRARkJD41X8VbBCzwAJGiQn97CC2sICzxMTdc1hAbBYBVYll7/ewgdi8Ah4SDW9WQS1T lJix5BlYL6eAp8T3OdvAbCGgmjVH9zBOYORdwMiwilE0tSC5oDgpPddQrzgxt7g0L10vOT93 EyM4kp5J7WBc2WBxiFGAg1GJh7dihXKQEGtiWXFl7iFGCQ5mJRHehmqVICHelMTKqtSi/Pii 0pzU4kOMyUBXTWSWEk3OB0Z5Xkm8obGJuamxqaWJhYmZJWnCSuK8B1qtA4UE0hNLUrNTUwtS i2C2MHFwSjUwtn75d3ftg9RQj9rLT/KDSx/NfZLoyLP9yat1XuafGGQD8v/cKWxIci2v0vew nZbKX/pQaMntnBOdQaI5102metccb7QUlRHLa9CYw7aLzVFqT5Tkof2Pp6ybaOPc+2BfxjSZ 9LYTDXuvMDOHxX1p+2B6uFdyAdPeyWwMj+/xfNexuvxo/eIMJZbijERDLeai4kQA5W2NQegC AAA= DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: rajeshwari.s@samsung.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Akshay Saraswat This patch intends to add DDR3 initialization code for Exynos5420. Signed-off-by: Rajeshwari S Shinde Signed-off-by: Akshay Saraswat --- arch/arm/cpu/armv7/exynos/dmc_common.c | 8 - arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 411 +++++++++++++++++++++++++++++- arch/arm/include/asm/arch-exynos/cpu.h | 4 + arch/arm/include/asm/arch-exynos/dmc.h | 121 ++++++--- 4 files changed, 502 insertions(+), 42 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c index 53cfe6e..882cd1e 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_common.c +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c @@ -152,14 +152,6 @@ void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) } } -void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc) -{ - writel(mem->memconfig, &dmc->memconfig0); - writel(mem->memconfig, &dmc->memconfig1); - writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0); - writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1); -} - void mem_ctrl_init(int reset) { struct spl_machine_param *param = spl_get_machine_params(); diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c index 5f5914e..71e69f8 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -15,8 +15,9 @@ #include "exynos5_setup.h" #include "clock_init.h" -#define RDLVL_COMPLETE_TIMEOUT 10000 +#define TIMEOUT 10000 +#ifdef CONFIG_EXYNOS5250 static void reset_phy_ctrl(void) { struct exynos5_clock *clk = @@ -174,7 +175,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val, &phy1_ctrl->phy_con1); writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config); - i = RDLVL_COMPLETE_TIMEOUT; + i = TIMEOUT; while ((readl(&dmc->phystatus) & (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) != (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) { @@ -215,3 +216,409 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), &dmc->concontrol); return 0; } +#endif + +#ifdef CONFIG_EXYNOS5420 +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, + int reset) +{ + struct exynos5420_clock *clk = + (struct exynos5420_clock *)EXYNOS5_CLOCK_BASE; + struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; + struct exynos5_dmc *drex0, *drex1; + struct exynos5_tzasc *tzasc0, *tzasc1; + uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1; + int chip; + int i; + + phy0_ctrl = (struct exynos5_phy_control *)samsung_get_base_dmc_phy(); + phy1_ctrl = (struct exynos5_phy_control *)(samsung_get_base_dmc_phy() + + DMC_OFFSET); + drex0 = (struct exynos5_dmc *)samsung_get_base_dmc_ctrl(); + drex1 = (struct exynos5_dmc *)(samsung_get_base_dmc_ctrl() + + DMC_OFFSET); + tzasc0 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC0_BASE; + tzasc1 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC1_BASE; + + /* Enable PAUSE for DREX */ + setbits_le32(&clk->pause, ENABLE_BIT); + + /* Enable BYPASS mode */ + setbits_le32(&clk->bpll_con1, BYPASS_EN); + + writel(MUX_BPLL_SEL_FOUTBPLL, &clk->src_cdrex); + do { + val = readl(&clk->mux_stat_cdrex); + val &= BPLL_SEL_MASK; + } while (val != FOUTBPLL); + + clrbits_le32(&clk->bpll_con1, BYPASS_EN); + + /* Specify the DDR memory type as DDR3 */ + val = readl(&phy0_ctrl->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &phy0_ctrl->phy_con0); + + val = readl(&phy1_ctrl->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &phy1_ctrl->phy_con0); + + /* Set Read Latency and Burst Length for PHY0 and PHY1 */ + val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) | + (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT); + writel(val, &phy0_ctrl->phy_con42); + writel(val, &phy1_ctrl->phy_con42); + + val = readl(&phy0_ctrl->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &phy0_ctrl->phy_con26); + + val = readl(&phy1_ctrl->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &phy1_ctrl->phy_con26); + + /* Set Driver strength for CK, CKE, CS & CA to 0x7 + * Set Driver strength for Data Slice 0~3 to 0x7 + */ + val = (0x7 << CA_CK_DRVR_DS_OFFSET) | (0x7 << CA_CKE_DRVR_DS_OFFSET) | + (0x7 << CA_CS_DRVR_DS_OFFSET) | (0x7 << CA_ADR_DRVR_DS_OFFSET); + val |= (0x7 << DA_3_DS_OFFSET) | (0x7 << DA_2_DS_OFFSET) | + (0x7 << DA_1_DS_OFFSET) | (0x7 << DA_0_DS_OFFSET); + writel(val, &phy0_ctrl->phy_con39); + writel(val, &phy1_ctrl->phy_con39); + + /* ZQ Calibration */ + if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl)) + return SETUP_ERR_ZQ_CALIBRATION_FAILURE; + + clrbits_le32(&phy0_ctrl->phy_con16, ZQ_CLK_DIV_EN); + clrbits_le32(&phy1_ctrl->phy_con16, ZQ_CLK_DIV_EN); + + /* DQ Signal */ + val = readl(&phy0_ctrl->phy_con14); + val |= mem->phy0_pulld_dqs; + writel(val, &phy0_ctrl->phy_con14); + val = readl(&phy1_ctrl->phy_con14); + val |= mem->phy1_pulld_dqs; + writel(val, &phy1_ctrl->phy_con14); + + val = MEM_TERM_EN | PHY_TERM_EN; + writel(val, &drex0->phycontrol0); + writel(val, &drex1->phycontrol0); + + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &drex0->concontrol); + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &drex1->concontrol); + + do { + val = readl(&drex0->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + do { + val = readl(&drex1->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + + clrbits_le32(&drex0->concontrol, DFI_INIT_START); + clrbits_le32(&drex1->concontrol, DFI_INIT_START); + + update_reset_dll(drex0, DDR_MODE_DDR3); + update_reset_dll(drex1, DDR_MODE_DDR3); + + /* Set Base Address: + * 0x2000_0000 ~ 0x5FFF_FFFF + * 0x6000_0000 ~ 0x9FFF_FFFF + */ + /* MEMBASECONFIG0 */ + val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_0) | + DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK); + writel(val, &tzasc0->membaseconfig0); + writel(val, &tzasc1->membaseconfig0); + + /* MEMBASECONFIG1 */ + val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_1) | + DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK); + writel(val, &tzasc0->membaseconfig1); + writel(val, &tzasc1->membaseconfig1); + + /* Memory Channel Inteleaving Size + * Ares Channel interleaving = 128 bytes + */ + /* MEMCONFIG0/1 */ + writel(mem->memconfig, &tzasc0->memconfig0); + writel(mem->memconfig, &tzasc1->memconfig0); + writel(mem->memconfig, &tzasc0->memconfig1); + writel(mem->memconfig, &tzasc1->memconfig1); + + /* Precharge Configuration */ + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &drex0->prechconfig0); + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &drex1->prechconfig0); + + /* TimingRow, TimingData, TimingPower and Timingaref + * values as per Memory AC parameters + */ + writel(mem->timing_ref, &drex0->timingref); + writel(mem->timing_ref, &drex1->timingref); + writel(mem->timing_row, &drex0->timingrow); + writel(mem->timing_row, &drex1->timingrow); + writel(mem->timing_data, &drex0->timingdata); + writel(mem->timing_data, &drex1->timingdata); + writel(mem->timing_power, &drex0->timingpower); + writel(mem->timing_power, &drex1->timingpower); + + if (reset) { + /* Send NOP, MRS and ZQINIT commands + * Sending MRS command will reset the DRAM. We should not be + * reseting the DRAM after resume, this will lead to memory + * corruption as DRAM content is lost after DRAM reset + */ + dmc_config_mrs(mem, drex0); + dmc_config_mrs(mem, drex1); + } else { + /* + * During Suspend-Resume & S/W-Reset, as soon as PMU releases + * pad retention, CKE goes high. This causes memory contents + * not to be retained during DRAM initialization. Therfore, + * there is a new control register(0x100431e8[28]) which lets us + * release pad retention and retain the memory content until the + * initialization is complete. + */ + writel(PAD_RETENTION_DRAM_COREBLK_VAL, + PAD_RETENTION_DRAM_COREBLK_OPTION); + do { + val = readl(PAD_RETENTION_DRAM_STATUS); + } while (val != 0x1); + + /* + * CKE PAD retention disables DRAM self-refresh mode. + * Send auto refresh command for DRAM refresh. + */ + for (i = 0; i < 128; i++) { + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + } + } + + if (mem->gate_leveling_enable) { + writel(PHY_CON0_RESET_VAL, &phy0_ctrl->phy_con0); + writel(PHY_CON0_RESET_VAL, &phy1_ctrl->phy_con0); + + setbits_le32(&phy0_ctrl->phy_con0, P0_CMD_EN); + setbits_le32(&phy1_ctrl->phy_con0, P0_CMD_EN); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + writel(val, &phy0_ctrl->phy_con2); + writel(val, &phy1_ctrl->phy_con2); + + val = readl(&phy0_ctrl->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &phy0_ctrl->phy_con1); + + val = readl(&phy1_ctrl->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &phy1_ctrl->phy_con1); + + n_lock_r = readl(&phy0_ctrl->phy_con13); + n_lock_w_phy0 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_r = readl(&phy0_ctrl->phy_con12); + n_lock_r &= ~CTRL_DLL_ON; + n_lock_r |= n_lock_w_phy0; + writel(n_lock_r, &phy0_ctrl->phy_con12); + + n_lock_r = readl(&phy1_ctrl->phy_con13); + n_lock_w_phy1 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2; + n_lock_r = readl(&phy1_ctrl->phy_con12); + n_lock_r &= ~CTRL_DLL_ON; + n_lock_r |= n_lock_w_phy1; + writel(n_lock_r, &phy1_ctrl->phy_con12); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + setbits_le32(&phy0_ctrl->phy_con2, RDLVL_GATE_EN); + setbits_le32(&phy1_ctrl->phy_con2, RDLVL_GATE_EN); + + setbits_le32(&phy0_ctrl->phy_con0, CTRL_SHGATE); + setbits_le32(&phy1_ctrl->phy_con0, CTRL_SHGATE); + + val = readl(&phy0_ctrl->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &phy0_ctrl->phy_con1); + + val = readl(&phy1_ctrl->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &phy1_ctrl->phy_con1); + + writel(CTRL_RDLVL_GATE_ENABLE, &drex0->rdlvl_config); + i = TIMEOUT; + while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) != + RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + writel(CTRL_RDLVL_GATE_DISABLE, &drex0->rdlvl_config); + + writel(CTRL_RDLVL_GATE_ENABLE, &drex1->rdlvl_config); + i = TIMEOUT; + while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) != + RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + writel(CTRL_RDLVL_GATE_DISABLE, &drex1->rdlvl_config); + + writel(0, &phy0_ctrl->phy_con14); + writel(0, &phy1_ctrl->phy_con14); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT); + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + if (mem->read_leveling_enable) { + /* Set Read DQ Calibration */ + val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + val = readl(&phy0_ctrl->phy_con1); + val |= READ_LEVELLING_DDR3; + writel(val, &phy0_ctrl->phy_con1); + val = readl(&phy1_ctrl->phy_con1); + val |= READ_LEVELLING_DDR3; + writel(val, &phy1_ctrl->phy_con1); + + val = readl(&phy0_ctrl->phy_con2); + val |= (RDLVL_EN | RDLVL_INCR_ADJ); + writel(val, &phy0_ctrl->phy_con2); + val = readl(&phy1_ctrl->phy_con2); + val |= (RDLVL_EN | RDLVL_INCR_ADJ); + writel(val, &phy1_ctrl->phy_con2); + + setbits_le32(&drex0->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + i = TIMEOUT; + while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take + * to timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + + clrbits_le32(&drex0->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + setbits_le32(&drex1->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + i = TIMEOUT; + while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take + * to timeout + */ + sdelay(100); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + + clrbits_le32(&drex1->rdlvl_config, + CTRL_RDLVL_DATA_ENABLE); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT); + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &drex1->directcmd); + } + + update_reset_dll(drex0, DDR_MODE_DDR3); + update_reset_dll(drex1, DDR_MODE_DDR3); + } + + /* Common Settings for Leveling */ + val = PHY_CON12_RESET_VAL; + writel((val + n_lock_w_phy0), &phy0_ctrl->phy_con12); + writel((val + n_lock_w_phy1), &phy1_ctrl->phy_con12); + + setbits_le32(&phy0_ctrl->phy_con2, DLL_DESKEW_EN); + setbits_le32(&phy1_ctrl->phy_con2, DLL_DESKEW_EN); + } + + /* Send PALL command */ + dmc_config_prech(mem, drex0); + dmc_config_prech(mem, drex1); + + writel(mem->memcontrol, &drex0->memcontrol); + writel(mem->memcontrol, &drex1->memcontrol); + + /* + * Set DMC Concontrol: Enable auto-refresh counter, provide + * read data fetch cycles and enable DREX auto set powerdown + * for input buffer of I/O in none read memory state. + */ + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &drex0->concontrol); + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &drex1->concontrol); + + /* Enable Clock Gating Control for DMC + * this saves around 25 mw dmc power as compared to the power + * consumption without these bits enabled + */ + setbits_le32(&drex0->cgcontrol, DMC_INTERNAL_CG); + setbits_le32(&drex1->cgcontrol, DMC_INTERNAL_CG); + + return 0; +} +#endif diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index e988251..a110240 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -160,6 +160,10 @@ #define EXYNOS5420_MODEM_BASE DEVICE_NOT_AVAILABLE #define EXYNOS5420_TZPC_BASE DEVICE_NOT_AVAILABLE +#define PAD_RETENTION_DRAM_STATUS (EXYNOS5420_POWER_BASE + 0x3004) +#define PAD_RETENTION_DRAM_COREBLK_OPTION (EXYNOS5420_POWER_BASE + 0x31E8) +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 + #ifndef __ASSEMBLY__ #include /* CPU detection macros */ diff --git a/arch/arm/include/asm/arch-exynos/dmc.h b/arch/arm/include/asm/arch-exynos/dmc.h index f65c676..b947de1 100644 --- a/arch/arm/include/asm/arch-exynos/dmc.h +++ b/arch/arm/include/asm/arch-exynos/dmc.h @@ -114,13 +114,22 @@ struct exynos4_dmc { struct exynos5_dmc { unsigned int concontrol; unsigned int memcontrol; + +/* Between 5250 and 5420, the DMC Register differs only at 0x8 offset. + * So to use the same structure and simplify the code put a define to + * distinguish between memconfig0 and cgcontrol register */ +#ifdef CONFIG_EXYNOS5250 unsigned int memconfig0; +#else + unsigned int cgcontrol; +#endif unsigned int memconfig1; unsigned int directcmd; - unsigned int prechconfig; + unsigned int prechconfig0; unsigned int phycontrol0; - unsigned char res1[0xc]; - unsigned int pwrdnconfig; + unsigned int prechconfig1; + unsigned char res1[0x8]; + unsigned int pwrdnconfig; /* 0x0028*/ unsigned int timingpzq; unsigned int timingref; unsigned int timingrow; @@ -128,12 +137,12 @@ struct exynos5_dmc { unsigned int timingpower; unsigned int phystatus; unsigned char res2[0x4]; - unsigned int chipstatus_ch0; + unsigned int chipstatus_ch0; /* 0x0048 */ unsigned int chipstatus_ch1; unsigned char res3[0x4]; unsigned int mrstatus; unsigned char res4[0x8]; - unsigned int qoscontrol0; + unsigned int qoscontrol0; /* 0x0060 */ unsigned char resr5[0x4]; unsigned int qoscontrol1; unsigned char res6[0x4]; @@ -164,45 +173,83 @@ struct exynos5_dmc { unsigned int qoscontrol14; unsigned char res19[0x4]; unsigned int qoscontrol15; - unsigned char res20[0x14]; + unsigned char res20[0x4]; + unsigned int timing_set_sw; /* 0x00e0 */ + unsigned int timingrow1; + unsigned int timingdata1; + unsigned int timingpower1; unsigned int ivcontrol; unsigned int wrtra_config; unsigned int rdlvl_config; - unsigned char res21[0x8]; + unsigned char res21[0x4]; + unsigned int brbrsvcontrol; /* 0x0100*/ unsigned int brbrsvconfig; unsigned int brbqosconfig; unsigned int membaseconfig0; - unsigned int membaseconfig1; + unsigned int membaseconfig1; /* 0x0110 */ unsigned char res22[0xc]; - unsigned int wrlvl_config; - unsigned char res23[0xc]; - unsigned int perevcontrol; + unsigned int wrlvl_config0; /* 0x0120 */ + unsigned int wrlvl_config1; + unsigned int wrlvl_status; + unsigned char res23[0x4]; + unsigned int perevcontrol; /* 0x0130 */ unsigned int perev0config; unsigned int perev1config; unsigned int perev2config; unsigned int perev3config; - unsigned char res24[0xdebc]; - unsigned int pmnc_ppc_a; - unsigned char res25[0xc]; - unsigned int cntens_ppc_a; - unsigned char res26[0xc]; - unsigned int cntenc_ppc_a; - unsigned char res27[0xc]; - unsigned int intens_ppc_a; - unsigned char res28[0xc]; - unsigned int intenc_ppc_a; - unsigned char res29[0xc]; - unsigned int flag_ppc_a; - unsigned char res30[0xac]; - unsigned int ccnt_ppc_a; - unsigned char res31[0xc]; - unsigned int pmcnt0_ppc_a; + unsigned char res22a[0xc]; + unsigned int ctrl_io_rdata_ch0; + unsigned int ctrl_io_rdata_ch1; + unsigned char res23a[0x8]; + unsigned int cacal_config0; + unsigned int cacal_config1; + unsigned int cacal_status; + unsigned char res24[0x94]; + unsigned int emergent_config0; /* 0x0200 */ + unsigned int emergent_config1; + unsigned char res25[0x8]; + unsigned int bp_control0; + unsigned int bp_control0_r; + unsigned int bp_control0_w; + unsigned char res26[0x4]; + unsigned int bp_control1; + unsigned int bp_control1_r; + unsigned int bp_control1_w; + unsigned char res27[0x4]; + unsigned int bp_control2; + unsigned int bp_control2_r; + unsigned int bp_control2_w; + unsigned char res28[0x4]; + unsigned int bp_control3; + unsigned int bp_control3_r; + unsigned int bp_control3_w; + unsigned char res29[0xb4]; + unsigned int winconfig_odt_w; /* 0x0300 */ + unsigned char res30[0x4]; + unsigned int winconfig_ctrl_read; + unsigned int winconfig_ctrl_gate; + unsigned char res31[0xdcf0]; + unsigned int pmnc_ppc; unsigned char res32[0xc]; - unsigned int pmcnt1_ppc_a; + unsigned int cntens_ppc; unsigned char res33[0xc]; - unsigned int pmcnt2_ppc_a; + unsigned int cntenc_ppc; unsigned char res34[0xc]; - unsigned int pmcnt3_ppc_a; + unsigned int intens_ppc; + unsigned char res35[0xc]; + unsigned int intenc_ppc; + unsigned char res36[0xc]; + unsigned int flag_ppc; /* 0xe050 */ + unsigned char res37[0xac]; + unsigned int ccnt_ppc; + unsigned char res38[0xc]; + unsigned int pmcnt0_ppc; + unsigned char res39[0xc]; + unsigned int pmcnt1_ppc; + unsigned char res40[0xc]; + unsigned int pmcnt2_ppc; + unsigned char res41[0xc]; + unsigned int pmcnt3_ppc; /* 0xe140 */ }; struct exynos5_phy_control { @@ -211,13 +258,13 @@ struct exynos5_phy_control { unsigned int phy_con2; unsigned int phy_con3; unsigned int phy_con4; - unsigned char res1[4]; + unsigned int phy_con5; unsigned int phy_con6; unsigned char res2[4]; unsigned int phy_con8; unsigned int phy_con9; unsigned int phy_con10; - unsigned char res3[4]; + unsigned int phy_con11; unsigned int phy_con12; unsigned int phy_con13; unsigned int phy_con14; @@ -252,6 +299,15 @@ struct exynos5_phy_control { unsigned int phy_con42; }; +struct exynos5_tzasc { + unsigned char res1[0xf00]; + unsigned int membaseconfig0; + unsigned int membaseconfig1; + unsigned char res2[0x8]; + unsigned int memconfig0; + unsigned int memconfig1; +}; + enum ddr_mode { DDR_MODE_DDR2, DDR_MODE_DDR3, @@ -286,6 +342,7 @@ enum mem_manuf { #define PHY_CON0_T_WRRDCMD_SHIFT 17 #define PHY_CON0_T_WRRDCMD_MASK (0x7 << PHY_CON0_T_WRRDCMD_SHIFT) #define PHY_CON0_CTRL_DDR_MODE_SHIFT 11 +#define PHY_CON0_CTRL_DDR_MODE_MASK 0x3 /* PHY_CON1 register fields */ #define PHY_CON1_RDLVL_RDDATA_ADJ_SHIFT 0