2 * Mem setup common file for different types of DDR present on SMDK5250 boards.
4 * Copyright (C) 2012 Samsung Electronics
6 * See file CREDITS for list of people who contributed to this
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 #include <asm/arch/spl.h>
28 #include "clock_init.h"
29 #include "common_setup.h"
30 #include "exynos5_setup.h"
32 #define ZQ_INIT_TIMEOUT 10000
34 int dmc_config_zq(struct mem_timings *mem,
35 struct exynos5_phy_control *phy0_ctrl,
36 struct exynos5_phy_control *phy1_ctrl)
38 unsigned long val = 0;
43 * Select Driver Strength,
44 * long calibration for manual calibration
46 val = PHY_CON16_RESET_VAL;
47 val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
48 val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
50 writel(val, &phy0_ctrl->phy_con16);
51 writel(val, &phy1_ctrl->phy_con16);
53 /* Disable termination */
54 if (mem->zq_mode_noterm)
55 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
56 writel(val, &phy0_ctrl->phy_con16);
57 writel(val, &phy1_ctrl->phy_con16);
59 /* ZQ_MANUAL_START: Enable */
61 writel(val, &phy0_ctrl->phy_con16);
62 writel(val, &phy1_ctrl->phy_con16);
64 /* ZQ_MANUAL_START: Disable */
65 val &= ~ZQ_MANUAL_STR;
68 * Since we are manaully calibrating the ZQ values,
69 * we are looping for the ZQ_init to complete.
72 while ((readl(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
78 writel(val, &phy0_ctrl->phy_con16);
81 while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
87 writel(val, &phy1_ctrl->phy_con16);
92 void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode)
96 if (mode == DDR_MODE_DDR3) {
97 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
98 writel(val, &dmc->phycontrol0);
101 /* Update DLL Information: Force DLL Resyncronization */
102 val = readl(&dmc->phycontrol0);
104 writel(val, &dmc->phycontrol0);
106 /* Reset Force DLL Resyncronization */
107 val = readl(&dmc->phycontrol0);
109 writel(val, &dmc->phycontrol0);
112 void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc)
116 for (channel = 0; channel < mem->dmc_channels; channel++) {
119 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
120 for (chip = 0; chip < mem->chips_to_configure; chip++) {
123 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
125 /* Sending NOP command */
126 writel(DIRECT_CMD_NOP | mask, &dmc->directcmd);
129 * TODO(alim.akhtar@samsung.com): Do we need these
130 * delays? This one and the next were not there for
135 /* Sending EMRS/MRS commands */
136 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
137 writel(mem->direct_cmd_msr[i] | mask,
142 if (mem->send_zq_init) {
143 /* Sending ZQINIT command */
144 writel(DIRECT_CMD_ZQINIT | mask,
153 void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc)
157 for (channel = 0; channel < mem->dmc_channels; channel++) {
160 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
161 for (chip = 0; chip < mem->chips_per_channel; chip++) {
162 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
164 /* PALL (all banks precharge) CMD */
165 writel(DIRECT_CMD_PALL | mask, &dmc->directcmd);
171 void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc)
173 writel(mem->memconfig, &dmc->memconfig0);
174 writel(mem->memconfig, &dmc->memconfig1);
175 writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0);
176 writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1);
179 void mem_ctrl_init(int reset)
181 struct spl_machine_param *param = spl_get_machine_params();
182 struct mem_timings *mem;
185 mem = clock_get_mem_timings();
187 /* If there are any other memory variant, add their init call below */
188 if (param->mem_type == DDR_MODE_DDR3) {
189 ret = ddr3_mem_ctrl_init(mem, param->mem_iv_size, reset);
191 /* will hang if failed to init memory control */
196 /* will hang if unknow memory type */