From patchwork Mon Dec 16 08:42:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajeshwari Shinde X-Patchwork-Id: 22510 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f198.google.com (mail-ob0-f198.google.com [209.85.214.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 27C9A23FC7 for ; Mon, 16 Dec 2013 08:41:23 +0000 (UTC) Received: by mail-ob0-f198.google.com with SMTP id wo20sf16790757obc.1 for ; Mon, 16 Dec 2013 00:41:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version: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=qPh2TENTTQ7tO47vvs2YagWwXLarDpp8l/JNqVOK2C8=; b=eWEG618rxuU3/L241aoe02VkabvtI01qJBamlIkQ84Ce0k/MYF4cGHSBmpLGKRYYKH AGYv5iwf+r0DCNAHITTN1gvCQNP5iLM/3e6yJ3xMF89logdj9Tsv+p+x9yzeqF00to0v WYyIO3f1NF68GJtmzV1MSoRNSvyEUQlso21iD5SU4uvd2LC50vJmvwcc9uri0w2J6sCC v00R/BDxXAJS4fnBdWxPW0HwCVcET4GawoYmEE76mnIhMsIr+QdHUts/m+o9v48wtb3Z cV4Jj3duoYiTOUka/+MqbkwnLLvlQFza5/1sjL6eAOPtv7Ft/8SSB5SyBVzOHmGUIoBZ Feuw== X-Gm-Message-State: ALoCoQlJ74XPp6NF8wIEuPJnKL7cRHl8hW3wQHBlO1UeqV/tDI9/+B4nXvdQqBzi/c8P33lrdn/5 X-Received: by 10.182.114.73 with SMTP id je9mr5631576obb.23.1387183282747; Mon, 16 Dec 2013 00:41:22 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.119.196 with SMTP id kw4ls1884190qeb.90.gmail; Mon, 16 Dec 2013 00:41:22 -0800 (PST) X-Received: by 10.220.182.137 with SMTP id cc9mr55417vcb.62.1387183282607; Mon, 16 Dec 2013 00:41:22 -0800 (PST) Received: from mail-vc0-f169.google.com (mail-vc0-f169.google.com [209.85.220.169]) by mx.google.com with ESMTPS id cp3si3811883vcb.133.2013.12.16.00.41.22 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 16 Dec 2013 00:41:22 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.169 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.169; Received: by mail-vc0-f169.google.com with SMTP id hu19so2996860vcb.0 for ; Mon, 16 Dec 2013 00:41:22 -0800 (PST) X-Received: by 10.220.116.197 with SMTP id n5mr1366366vcq.42.1387183282505; Mon, 16 Dec 2013 00:41:22 -0800 (PST) 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 u4csp81870vcz; Mon, 16 Dec 2013 00:41:21 -0800 (PST) X-Received: by 10.66.51.137 with SMTP id k9mr19093208pao.11.1387183278863; Mon, 16 Dec 2013 00:41:18 -0800 (PST) Received: from mailout4.samsung.com (mailout4.samsung.com. [203.254.224.34]) by mx.google.com with ESMTPS id ek3si8256032pbd.145.2013.12.16.00.41.18 for (version=TLSv1 cipher=RC4-MD5 bits=128/128); Mon, 16 Dec 2013 00:41:18 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of rajeshwari.s@samsung.com designates 203.254.224.34 as permitted sender) client-ip=203.254.224.34; Received: from epcpsbgr2.samsung.com (u142.gpu120.samsung.co.kr [203.254.230.142]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MXW00KQM5GS5FC0@mailout4.samsung.com>; Mon, 16 Dec 2013 17:41:16 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.122]) by epcpsbgr2.samsung.com (EPCPMTA) with SMTP id 84.DF.06250.CACBEA25; Mon, 16 Dec 2013 17:41:16 +0900 (KST) X-AuditID: cbfee68e-b7fb46d00000186a-91-52aebcac98cb Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 90.06.20899.CACBEA25; Mon, 16 Dec 2013 17:41:16 +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 <0MXW00AYZ5G8P680@mmp2.samsung.com>; Mon, 16 Dec 2013 17:41:16 +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, alim.akhtar@samsung.com Subject: [PATCH 06/11 V11] Exynos5420: Add DDR3 initialization for 5420 Date: Mon, 16 Dec 2013 14:12:39 +0530 Message-id: <1387183364-20546-7-git-send-email-rajeshwari.s@samsung.com> X-Mailer: git-send-email 1.7.11.7 In-reply-to: <1387183364-20546-1-git-send-email-rajeshwari.s@samsung.com> References: <1387183364-20546-1-git-send-email-rajeshwari.s@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrOLMWRmVeSWpSXmKPExsWyRsSkSnfNnnVBBj/b5C0ezNvGZvFw/U0W i44jLYwWUw5/YbH4tmUbo8Xy1xvZLd7u7WR3YPeY3XCRxWPBplKPO9f2sHmcvbOD0aNvyyrG ANYoLpuU1JzMstQifbsEroyrfQ2sBWcfMlbsWXSFsYFxw07GLkYODgkBE4l/96W6GDmBTDGJ C/fWs3UxcnEICSxllOi78YIdImEi8X/vYSaIxHRGiY+f5kA5XUwSjS2fmUAmsQFVbTyRANIg IiAh8av/KiNIDbNAP1DD7v+sIAlhAXeJWa8usoHYLAKqElv/zmcD6eUV8JA4+iEGYpmixIwl zxhBbE4BT4nLT5YxgdhCQCUvOu+AzZQQWMQu8ezYNRaIOQIS3yYfYoH4RlZi0wFmiDmSEgdX 3GCZwCi8gJFhFaNoakFyQXFSepGRXnFibnFpXrpecn7uJkZgoJ/+96xvB+PNA9aHGJOBxk1k lhJNzgdGSl5JvKGxmZGFqYmpsZG5pRlpwkrivIseJgUJCaQnlqRmp6YWpBbFF5XmpBYfYmTi 4JRqYFTa/733nMWKZ0aX19u/cZuycLJ3yC3Hpdxrr/idWLTxjLj1TCknzwC1R3OuXJMqrw5m EDVWvLvHZc3M4l2X7kWmTIqftX5R2gV/tmIh04c1fKz2LLOzJGWu8LA8jZh458VTr+nTThvW fK0Qk1zjweu4yVpkmkvMQ9eqv2qsl64FB8wT3bl0/kMlluKMREMt5qLiRAD4viA/igIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrKIsWRmVeSWpSXmKPExsVy+t9jQd01e9YFGazcLGzxYN42NouH62+y WHQcaWG0mHL4C4vFty3bGC2Wv97IbvF2bye7A7vH7IaLLB4LNpV63Lm2h83j7J0djB59W1Yx BrBGNTDaZKQmpqQWKaTmJeenZOal2yp5B8c7x5uaGRjqGlpamCsp5CXmptoqufgE6Lpl5gDd oaRQlphTChQKSCwuVtK3wzQhNMRN1wKmMULXNyQIrsfIAA0krGHMuNrXwFpw9iFjxZ5FVxgb GDfsZOxi5OSQEDCR+L/3MBOELSZx4d56ti5GLg4hgemMEh8/zWGCcLqYJBpbPgM5HBxsQB0b TySANIgISEj86r/KCFLDLNAP1LD7PytIQljAXWLWq4tsIDaLgKrE1r/z2UB6eQU8JI5+iIFY pigxY8kzsCM4BTwlLj9ZBnaEEFDJi847jBMYeRcwMqxiFE0tSC4oTkrPNdIrTswtLs1L10vO z93ECI6kZ9I7GFc1WBxiFOBgVOLhVbBcFyTEmlhWXJl7iFGCg1lJhDfm6togId6UxMqq1KL8 +KLSnNTiQ4zJQEdNZJYSTc4HRnleSbyhsYm5qbGppYmFiZklacJK4rwHW60DhQTSE0tSs1NT C1KLYLYwcXBKNTBKn/rTrLvlXpl5+Ew/4SVJx1avsN4RVKtZcHZiz6GFD2/wXUkxeSB36Ju0 vJplpMeu7GVlbJz7wt0nJHEpRfV92fjJ5F/KfiP+JYbTH7DY3Z2xRY+7KqeOI7dgy+X5Jz0Y rJMarITnvHQ3nrHtgUi68P84Dn3NHkbFLx2TXVdnC9+vObxG2l6JpTgj0VCLuag4EQBzmuWH 6AIAAA== 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.220.169 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: , This patch intends to add DDR3 initialization code for Exynos5420. Signed-off-by: Akshay Saraswat Signed-off-by: Rajeshwari S Shinde --- Changes in V2: - Corrected a compilation issue for SMDK5250. Changes in V3: - None Changes in V4: - None Changes in V5: - None Changes in V6: - None Changes in V7: - Fixed multi line comment. Changes in V8: - None Changes in V9: - Used samsung_get base to get the dmc base address Changes in V10: - Changed to new 5420 dmc and power resgister structure. - Changed the input parameters for dmc common functions due to changes in the dmc register structure. Changes in V11: - None arch/arm/cpu/armv7/exynos/dmc_common.c | 60 ++-- arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 439 +++++++++++++++++++++++++++++- arch/arm/cpu/armv7/exynos/exynos5_setup.h | 26 +- arch/arm/include/asm/arch-exynos/cpu.h | 7 +- arch/arm/include/asm/arch-exynos/dmc.h | 10 + 5 files changed, 484 insertions(+), 58 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c index 53cfe6e..520eac5 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_common.c +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c @@ -1,5 +1,5 @@ /* - * Mem setup common file for different types of DDR present on SMDK5250 boards. + * Mem setup common file for different types of DDR present on Exynos boards. * * Copyright (C) 2012 Samsung Electronics * @@ -15,9 +15,9 @@ #define ZQ_INIT_TIMEOUT 10000 -int dmc_config_zq(struct mem_timings *mem, - struct exynos5_phy_control *phy0_ctrl, - struct exynos5_phy_control *phy1_ctrl) +int dmc_config_zq(struct mem_timings *mem, const void *phy0_con16, + const void *phy1_con16, const void *phy0_con17, + const void *phy1_con17) { unsigned long val = 0; int i; @@ -31,19 +31,19 @@ int dmc_config_zq(struct mem_timings *mem, val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT; val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT; val |= ZQ_CLK_DIV_EN; - writel(val, &phy0_ctrl->phy_con16); - writel(val, &phy1_ctrl->phy_con16); + writel(val, phy0_con16); + writel(val, phy1_con16); /* Disable termination */ if (mem->zq_mode_noterm) val |= PHY_CON16_ZQ_MODE_NOTERM_MASK; - writel(val, &phy0_ctrl->phy_con16); - writel(val, &phy1_ctrl->phy_con16); + writel(val, phy0_con16); + writel(val, phy1_con16); /* ZQ_MANUAL_START: Enable */ val |= ZQ_MANUAL_STR; - writel(val, &phy0_ctrl->phy_con16); - writel(val, &phy1_ctrl->phy_con16); + writel(val, phy0_con16); + writel(val, phy1_con16); /* ZQ_MANUAL_START: Disable */ val &= ~ZQ_MANUAL_STR; @@ -53,47 +53,47 @@ int dmc_config_zq(struct mem_timings *mem, * we are looping for the ZQ_init to complete. */ i = ZQ_INIT_TIMEOUT; - while ((readl(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { + while ((readl(phy0_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { sdelay(100); i--; } if (!i) return -1; - writel(val, &phy0_ctrl->phy_con16); + writel(val, phy0_con16); i = ZQ_INIT_TIMEOUT; - while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { + while ((readl(phy1_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { sdelay(100); i--; } if (!i) return -1; - writel(val, &phy1_ctrl->phy_con16); + writel(val, phy1_con16); return 0; } -void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode) +void update_reset_dll(const void *phycontrol0, enum ddr_mode mode) { unsigned long val; if (mode == DDR_MODE_DDR3) { val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE; - writel(val, &dmc->phycontrol0); + writel(val, phycontrol0); } /* Update DLL Information: Force DLL Resyncronization */ - val = readl(&dmc->phycontrol0); + val = readl(phycontrol0); val |= FP_RSYNC; - writel(val, &dmc->phycontrol0); + writel(val, phycontrol0); /* Reset Force DLL Resyncronization */ - val = readl(&dmc->phycontrol0); + val = readl(phycontrol0); val &= ~FP_RSYNC; - writel(val, &dmc->phycontrol0); + writel(val, phycontrol0); } -void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) +void dmc_config_mrs(struct mem_timings *mem, const void *directcmd) { int channel, chip; @@ -107,7 +107,7 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) mask |= chip << DIRECT_CMD_CHIP_SHIFT; /* Sending NOP command */ - writel(DIRECT_CMD_NOP | mask, &dmc->directcmd); + writel(DIRECT_CMD_NOP | mask, directcmd); /* * TODO(alim.akhtar@samsung.com): Do we need these @@ -119,14 +119,14 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) /* Sending EMRS/MRS commands */ for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { writel(mem->direct_cmd_msr[i] | mask, - &dmc->directcmd); + directcmd); sdelay(0x10000); } if (mem->send_zq_init) { /* Sending ZQINIT command */ writel(DIRECT_CMD_ZQINIT | mask, - &dmc->directcmd); + directcmd); sdelay(10000); } @@ -134,7 +134,7 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) } } -void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) +void dmc_config_prech(struct mem_timings *mem, const void *directcmd) { int channel, chip; @@ -146,20 +146,12 @@ void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) mask |= chip << DIRECT_CMD_CHIP_SHIFT; /* PALL (all banks precharge) CMD */ - writel(DIRECT_CMD_PALL | mask, &dmc->directcmd); + writel(DIRECT_CMD_PALL | mask, directcmd); sdelay(0x10000); } } } -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..487e6f4 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -1,5 +1,5 @@ /* - * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 + * DDR3 mem setup file for board based on EXYNOS5 * * Copyright (C) 2012 Samsung Electronics * @@ -11,12 +11,14 @@ #include #include #include +#include #include "common_setup.h" #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 = @@ -57,7 +59,8 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val, &phy1_ctrl->phy_con42); /* ZQ Calibration */ - if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl)) + if (dmc_config_zq(mem, &phy0_ctrl->phy_con16, &phy1_ctrl->phy_con16, + &phy0_ctrl->phy_con17, &phy1_ctrl->phy_con17)) return SETUP_ERR_ZQ_CALIBRATION_FAILURE; /* DQ Signal */ @@ -68,7 +71,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, | (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT), &dmc->concontrol); - update_reset_dll(dmc, DDR_MODE_DDR3); + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); /* DQS Signal */ writel(mem->phy0_dqs, &phy0_ctrl->phy_con4); @@ -93,7 +96,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), &phy1_ctrl->phy_con12); - update_reset_dll(dmc, DDR_MODE_DDR3); + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), &dmc->concontrol); @@ -124,10 +127,10 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(mem->timing_power, &dmc->timingpower); /* Send PALL command */ - dmc_config_prech(mem, dmc); + dmc_config_prech(mem, &dmc->directcmd); /* Send NOP, MRS and ZQINIT commands */ - dmc_config_mrs(mem, dmc); + dmc_config_mrs(mem, &dmc->directcmd); if (mem->gate_leveling_enable) { val = PHY_CON0_RESET_VAL; @@ -174,7 +177,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) { @@ -202,11 +205,11 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, writel(val, &phy0_ctrl->phy_con12); writel(val, &phy1_ctrl->phy_con12); - update_reset_dll(dmc, DDR_MODE_DDR3); + update_reset_dll(&dmc->phycontrol0, DDR_MODE_DDR3); } /* Send PALL command */ - dmc_config_prech(mem, dmc); + dmc_config_prech(mem, &dmc->directcmd); writel(mem->memcontrol, &dmc->memcontrol); @@ -215,3 +218,419 @@ 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 *)samsung_get_base_clock(); + struct exynos5420_power *power = + (struct exynos5420_power *)samsung_get_base_power(); + struct exynos5420_phy_control *phy0_ctrl, *phy1_ctrl; + struct exynos5420_dmc *drex0, *drex1; + struct exynos5420_tzasc *tzasc0, *tzasc1; + uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1; + int chip; + int i; + + phy0_ctrl = (struct exynos5420_phy_control *)samsung_get_base_dmc_phy(); + phy1_ctrl = (struct exynos5420_phy_control *)(samsung_get_base_dmc_phy() + + DMC_OFFSET); + drex0 = (struct exynos5420_dmc *)samsung_get_base_dmc_ctrl(); + drex1 = (struct exynos5420_dmc *)(samsung_get_base_dmc_ctrl() + + DMC_OFFSET); + tzasc0 = (struct exynos5420_tzasc *)samsung_get_base_dmc_tzasc(); + tzasc1 = (struct exynos5420_tzasc *)(samsung_get_base_dmc_tzasc() + + DMC_OFFSET); + + /* 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->phy_con16, &phy1_ctrl->phy_con16, + &phy0_ctrl->phy_con17, &phy1_ctrl->phy_con17)) + 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->phycontrol0, DDR_MODE_DDR3); + update_reset_dll(&drex1->phycontrol0, 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->timingrow0); + writel(mem->timing_row, &drex1->timingrow0); + writel(mem->timing_data, &drex0->timingdata0); + writel(mem->timing_data, &drex1->timingdata0); + writel(mem->timing_power, &drex0->timingpower0); + writel(mem->timing_power, &drex1->timingpower0); + + 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->directcmd); + dmc_config_mrs(mem, &drex1->directcmd); + } 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, + &power->pad_retention_dram_coreblk_option); + do { + val = readl(&power->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->phycontrol0, DDR_MODE_DDR3); + update_reset_dll(&drex1->phycontrol0, 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->directcmd); + dmc_config_prech(mem, &drex1->directcmd); + + 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/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index c8d6515..c6a49c4 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -696,6 +696,7 @@ #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE #else +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 /* APLL_CON1 */ #define APLL_CON1_VAL (0x0020F300) @@ -907,37 +908,38 @@ void lpddr3_mem_ctrl_init(void); * Configure ZQ I/O interface * * @param mem Memory timings for this memory type. - * @param phy0_ctrl Pointer to struct containing PHY0 control reg - * @param phy1_ctrl Pointer to struct containing PHY1 control reg + * @param phy0_con16 Register address for dmc_phy0->phy_con16 + * @param phy1_con16 Register address for dmc_phy1->phy_con16 + * @param phy0_con17 Register address for dmc_phy0->phy_con17 + * @param phy1_con17 Register address for dmc_phy1->phy_con17 * @return 0 if ok, -1 on error */ -int dmc_config_zq(struct mem_timings *mem, - struct exynos5_phy_control *phy0_ctrl, - struct exynos5_phy_control *phy1_ctrl); - +int dmc_config_zq(struct mem_timings *mem, const void *phy0_con16, + const void *phy1_con16, const void *phy0_con17, + const void *phy1_con17); /* * Send NOP and MRS/EMRS Direct commands * * @param mem Memory timings for this memory type. - * @param dmc Pointer to struct of DMC registers + * @param directcmd Register address for dmc_phy->directcmd */ -void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc); +void dmc_config_mrs(struct mem_timings *mem, const void *directcmd); /* * Send PALL Direct commands * * @param mem Memory timings for this memory type. - * @param dmc Pointer to struct of DMC registers + * @param directcmd Register address for dmc_phy->directcmd */ -void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc); +void dmc_config_prech(struct mem_timings *mem, const void *directcmd); /* * Reset the DLL. This function is common between DDR3 and LPDDR2. * However, the reset value is different. So we are passing a flag * ddr_mode to distinguish between LPDDR2 and DDR3. * - * @param exynos5_dmc Pointer to struct of DMC registers + * @param phycontrol0 Register address for dmc_phy->phycontrol0 * @param ddr_mode Type of DDR memory */ -void update_reset_dll(struct exynos5_dmc *, enum ddr_mode); +void update_reset_dll(const void *phycontrol0, enum ddr_mode); #endif diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 2b44210..573f755 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -53,6 +53,7 @@ #define EXYNOS4_AUDIOSS_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_USB3PHY_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS4_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE /* EXYNOS4X12 */ #define EXYNOS4X12_GPIO_PART3_BASE 0x03860000 @@ -91,6 +92,7 @@ #define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS4X12_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE /* EXYNOS5 */ #define EXYNOS5_I2C_SPACING 0x10000 @@ -129,6 +131,7 @@ #define EXYNOS5_ADC_BASE DEVICE_NOT_AVAILABLE #define EXYNOS5_MODEM_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS5_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE /* EXYNOS5420 */ #define EXYNOS5420_AUDIOSS_BASE 0x03810000 @@ -143,8 +146,7 @@ #define EXYNOS5420_ACE_SFR_BASE 0x10830000 #define EXYNOS5420_DMC_PHY_BASE 0x10C00000 #define EXYNOS5420_DMC_CTRL_BASE 0x10C20000 -#define EXYNOS5420_DMC_TZASC0_BASE 0x10D40000 -#define EXYNOS5420_DMC_TZASC1_BASE 0x10D50000 +#define EXYNOS5420_DMC_TZASC_BASE 0x10D40000 #define EXYNOS5420_USB_HOST_EHCI_BASE 0x12110000 #define EXYNOS5420_MMC_BASE 0x12200000 #define EXYNOS5420_SROMC_BASE 0x12250000 @@ -284,6 +286,7 @@ SAMSUNG_BASE(spi_isp, SPI_ISP_BASE) SAMSUNG_BASE(tzpc, TZPC_BASE) SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE) SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE) +SAMSUNG_BASE(dmc_tzasc, DMC_TZASC_BASE) SAMSUNG_BASE(audio_ass, AUDIOSS_BASE) #endif diff --git a/arch/arm/include/asm/arch-exynos/dmc.h b/arch/arm/include/asm/arch-exynos/dmc.h index 32ad3ae..d78536d 100644 --- a/arch/arm/include/asm/arch-exynos/dmc.h +++ b/arch/arm/include/asm/arch-exynos/dmc.h @@ -419,6 +419,15 @@ struct exynos5420_phy_control { unsigned int phy_con42; }; +struct exynos5420_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, @@ -453,6 +462,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