blob: ebfe1e1a0fff41971671f1db7fd6b99d676537c1 [file] [log] [blame]
Gabe Black607c0b62013-05-16 05:45:57 -07001/*
2 * This file is part of the coreboot project.
3 *
Ronald G. Minniche6af9292013-06-03 13:03:50 -07004 * DDR3 mem setup file for EXYNOS5 based board
5 *
Gabe Black607c0b62013-05-16 05:45:57 -07006 * Copyright (C) 2012 Samsung Electronics
7 *
Ronald G. Minniche6af9292013-06-03 13:03:50 -07008 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
Gabe Black607c0b62013-05-16 05:45:57 -070015 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
Ronald G. Minniche6af9292013-06-03 13:03:50 -070023 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
Gabe Black607c0b62013-05-16 05:45:57 -070025 */
26
Gabe Black607c0b62013-05-16 05:45:57 -070027#include <console/console.h>
28#include <delay.h>
29#include <arch/io.h>
Gabe Black607c0b62013-05-16 05:45:57 -070030#include "dmc.h"
31#include "setup.h"
Ronald G. Minniche6af9292013-06-03 13:03:50 -070032#include "cpu.h"
33#include "clk.h"
Gabe Black607c0b62013-05-16 05:45:57 -070034
Ronald G. Minniche6af9292013-06-03 13:03:50 -070035#define TIMEOUT 10000
Gabe Black607c0b62013-05-16 05:45:57 -070036
Ronald G. Minniche6af9292013-06-03 13:03:50 -070037/* 'reset' field is currently ignored. */
38
39int ddr3_mem_ctrl_init(struct mem_timings *mem, int interleave_size, int reset)
Gabe Black607c0b62013-05-16 05:45:57 -070040{
Ronald G. Minniche6af9292013-06-03 13:03:50 -070041 struct exynos5420_clock *clk =
42 (struct exynos5420_clock *)EXYNOS5_CLOCK_BASE;
Gabe Black607c0b62013-05-16 05:45:57 -070043 struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
Ronald G. Minniche6af9292013-06-03 13:03:50 -070044 struct exynos5_dmc *drex0, *drex1;
45 struct exynos5_tzasc *tzasc0, *tzasc1;
46 u32 val, nLockR, nLockW_phy0, nLockW_phy1;
Gabe Black607c0b62013-05-16 05:45:57 -070047 int i;
48
49 phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE;
50 phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE;
Ronald G. Minniche6af9292013-06-03 13:03:50 -070051 drex0 = (struct exynos5_dmc *)EXYNOS5420_DMC_DREXI_0;
52 drex1 = (struct exynos5_dmc *)EXYNOS5420_DMC_DREXI_1;
53 tzasc0 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC_0;
54 tzasc1 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC_1;
Gabe Black607c0b62013-05-16 05:45:57 -070055
Ronald G. Minniche6af9292013-06-03 13:03:50 -070056 /* Enable PAUSE for DREX */
57 setbits_le32(&clk->pause, ENABLE_BIT);
Gabe Black607c0b62013-05-16 05:45:57 -070058
Ronald G. Minniche6af9292013-06-03 13:03:50 -070059 /* Enable BYPASS mode */
60 setbits_le32(&clk->bpll_con1, BYPASS_EN);
61
62 writel(MUX_BPLL_SEL_FOUTBPLL, &clk->clk_src_cdrex);
63 do {
64 val = readl(&clk->clk_mux_stat_cdrex);
65 val &= BPLL_SEL_MASK;
66 } while (val != FOUTBPLL);
67
68 clrbits_le32(&clk->bpll_con1, BYPASS_EN);
69
70 /* Specify the DDR memory type as DDR3 */
71 val = readl(&phy0_ctrl->phy_con0);
72 val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT);
73 val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT);
74 writel(val, &phy0_ctrl->phy_con0);
75
76 val = readl(&phy1_ctrl->phy_con0);
77 val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT);
78 val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT);
79 writel(val, &phy1_ctrl->phy_con0);
Gabe Black607c0b62013-05-16 05:45:57 -070080
81 /* Set Read Latency and Burst Length for PHY0 and PHY1 */
Gabe Black607c0b62013-05-16 05:45:57 -070082 val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) |
83 (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT);
84 writel(val, &phy0_ctrl->phy_con42);
85 writel(val, &phy1_ctrl->phy_con42);
86
Ronald G. Minniche6af9292013-06-03 13:03:50 -070087 val = readl(&phy0_ctrl->phy_con26);
88 val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET);
89 val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET);
90 writel(val, &phy0_ctrl->phy_con26);
91
92 val = readl(&phy1_ctrl->phy_con26);
93 val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET);
94 val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET);
95 writel(val, &phy1_ctrl->phy_con26);
96
97 /* Set Driver strength for CK, CKE, CS & CA to 0x7
98 * Set Driver strength for Data Slice 0~3 to 0x6
99 */
100 val = (0x7 << CA_CK_DRVR_DS_OFFSET) | (0x7 << CA_CKE_DRVR_DS_OFFSET) |
101 (0x7 << CA_CS_DRVR_DS_OFFSET) | (0x7 << CA_ADR_DRVR_DS_OFFSET);
102 val |= (0x6 << DA_3_DS_OFFSET) | (0x6 << DA_2_DS_OFFSET) |
103 (0x6 << DA_1_DS_OFFSET) | (0x6 << DA_0_DS_OFFSET);
104 writel(val, &phy0_ctrl->phy_con39);
105 writel(val, &phy1_ctrl->phy_con39);
106
Gabe Black607c0b62013-05-16 05:45:57 -0700107 /* ZQ Calibration */
Gabe Black607c0b62013-05-16 05:45:57 -0700108 if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl))
109 return SETUP_ERR_ZQ_CALIBRATION_FAILURE;
110
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700111 clrbits_le32(&phy0_ctrl->phy_con16, ZQ_CLK_DIV_EN);
112 clrbits_le32(&phy1_ctrl->phy_con16, ZQ_CLK_DIV_EN);
113
Gabe Black607c0b62013-05-16 05:45:57 -0700114 /* DQ Signal */
Gabe Black607c0b62013-05-16 05:45:57 -0700115 writel(mem->phy0_pulld_dqs, &phy0_ctrl->phy_con14);
116 writel(mem->phy1_pulld_dqs, &phy1_ctrl->phy_con14);
117
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700118 val = MEM_TERM_EN | PHY_TERM_EN;
119 writel(val, &drex0->phycontrol0);
120 writel(val, &drex1->phycontrol0);
Gabe Black607c0b62013-05-16 05:45:57 -0700121
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700122 writel(mem->concontrol |
123 (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) |
124 (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
125 &drex0->concontrol);
126 writel(mem->concontrol |
127 (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) |
128 (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
129 &drex1->concontrol);
Gabe Black607c0b62013-05-16 05:45:57 -0700130
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700131 do {
132 val = readl(&drex0->phystatus);
133 } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE);
134 do {
135 val = readl(&drex1->phystatus);
136 } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE);
Gabe Black607c0b62013-05-16 05:45:57 -0700137
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700138 clrbits_le32(&drex0->concontrol, DFI_INIT_START);
139 clrbits_le32(&drex1->concontrol, DFI_INIT_START);
Gabe Black607c0b62013-05-16 05:45:57 -0700140
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700141 update_reset_dll(drex0, DDR_MODE_DDR3);
142 update_reset_dll(drex1, DDR_MODE_DDR3);
Gabe Black607c0b62013-05-16 05:45:57 -0700143
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700144 /* Set Base Address:
145 * 0x2000_0000 ~ 0x5FFF_FFFF
146 * 0x6000_0000 ~ 0x9FFF_FFFF
147 */
148 /* MEMBASECONFIG0 */
149 val = DMC_MEMBASECONFIGx_CHIP_BASE(DMC_CHIP_BASE_0) |
150 DMC_MEMBASECONFIGx_CHIP_MASK(DMC_CHIP_MASK);
151 writel(val, &tzasc0->membaseconfig0);
152 writel(val, &tzasc1->membaseconfig0);
Gabe Black607c0b62013-05-16 05:45:57 -0700153
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700154 /* MEMBASECONFIG1 */
155 val = DMC_MEMBASECONFIGx_CHIP_BASE(DMC_CHIP_BASE_1) |
156 DMC_MEMBASECONFIGx_CHIP_MASK(DMC_CHIP_MASK);
157 writel(val, &tzasc0->membaseconfig1);
158 writel(val, &tzasc1->membaseconfig1);
Gabe Black607c0b62013-05-16 05:45:57 -0700159
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700160 /* Memory Channel Inteleaving Size
161 * Exynos5420 Channel interleaving = 128 bytes
162 */
163 /* MEMCONFIG0/1 */
164 writel(mem->memconfig, &tzasc0->memconfig0);
165 writel(mem->memconfig, &tzasc1->memconfig0);
166 writel(mem->memconfig, &tzasc0->memconfig1);
167 writel(mem->memconfig, &tzasc1->memconfig1);
Gabe Black607c0b62013-05-16 05:45:57 -0700168
169 /* Precharge Configuration */
Gabe Black607c0b62013-05-16 05:45:57 -0700170 writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700171 &drex0->prechconfig0);
172 writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
173 &drex1->prechconfig0);
Gabe Black607c0b62013-05-16 05:45:57 -0700174
175 /* TimingRow, TimingData, TimingPower and Timingaref
176 * values as per Memory AC parameters
177 */
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700178 writel(mem->timing_ref, &drex0->timingref);
179 writel(mem->timing_ref, &drex1->timingref);
180 writel(mem->timing_row, &drex0->timingrow);
181 writel(mem->timing_row, &drex1->timingrow);
182 writel(mem->timing_data, &drex0->timingdata);
183 writel(mem->timing_data, &drex1->timingdata);
184 writel(mem->timing_power, &drex0->timingpower);
185 writel(mem->timing_power, &drex1->timingpower);
Gabe Black607c0b62013-05-16 05:45:57 -0700186
Hung-Te Linc0491d42013-08-06 10:48:48 +0800187 /* Send NOP, MRS and ZQINIT commands.
188 * Sending MRS command will reset the DRAM. We should not be
189 * reseting the DRAM after resume, this will lead to memory
190 * corruption as DRAM content is lost after DRAM reset.
191 */
192 if (reset) {
193 dmc_config_mrs(mem, drex0);
194 dmc_config_mrs(mem, drex1);
195 }
Gabe Black607c0b62013-05-16 05:45:57 -0700196
197 if (mem->gate_leveling_enable) {
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700198
199 setbits_le32(&phy0_ctrl->phy_con0, CTRL_ATGATE);
200 setbits_le32(&phy1_ctrl->phy_con0, CTRL_ATGATE);
201
202 setbits_le32(&phy0_ctrl->phy_con0, P0_CMD_EN);
203 setbits_le32(&phy1_ctrl->phy_con0, P0_CMD_EN);
Gabe Black607c0b62013-05-16 05:45:57 -0700204
205 val = PHY_CON2_RESET_VAL;
206 val |= INIT_DESKEW_EN;
207 writel(val, &phy0_ctrl->phy_con2);
208 writel(val, &phy1_ctrl->phy_con2);
209
210 val = PHY_CON0_RESET_VAL;
211 val |= P0_CMD_EN;
212 val |= BYTE_RDLVL_EN;
213 writel(val, &phy0_ctrl->phy_con0);
214 writel(val, &phy1_ctrl->phy_con0);
215
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700216 val = readl(&phy0_ctrl->phy_con1);
217 val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
Gabe Black607c0b62013-05-16 05:45:57 -0700218 writel(val, &phy0_ctrl->phy_con1);
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700219
220 val = readl(&phy1_ctrl->phy_con1);
221 val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
Gabe Black607c0b62013-05-16 05:45:57 -0700222 writel(val, &phy1_ctrl->phy_con1);
223
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700224 nLockR = readl(&phy0_ctrl->phy_con13);
225 nLockW_phy0 = (nLockR & CTRL_LOCK_COARSE_MASK) >> 2;
226 nLockR = readl(&phy0_ctrl->phy_con12);
227 nLockR &= ~CTRL_DLL_ON;
228 nLockR |= nLockW_phy0;
229 writel(nLockR, &phy0_ctrl->phy_con12);
230
231 nLockR = readl(&phy1_ctrl->phy_con13);
232 nLockW_phy1 = (nLockR & CTRL_LOCK_COARSE_MASK) >> 2;
233 nLockR = readl(&phy1_ctrl->phy_con12);
234 nLockR &= ~CTRL_DLL_ON;
235 nLockR |= nLockW_phy1;
236 writel(nLockR, &phy1_ctrl->phy_con12);
237
238 writel(0x00030004, &drex0->directcmd);
239 writel(0x00130004, &drex0->directcmd);
240 writel(0x00030004, &drex1->directcmd);
241 writel(0x00130004, &drex1->directcmd);
242
243 setbits_le32(&phy0_ctrl->phy_con2, RDLVL_GATE_EN);
244 setbits_le32(&phy1_ctrl->phy_con2, RDLVL_GATE_EN);
245
246 setbits_le32(&phy0_ctrl->phy_con0, CTRL_SHGATE);
247 setbits_le32(&phy1_ctrl->phy_con0, CTRL_SHGATE);
248
249 val = readl(&phy0_ctrl->phy_con1);
250 val &= ~(CTRL_GATEDURADJ_MASK);
251 writel(val, &phy0_ctrl->phy_con1);
252
253 val = readl(&phy1_ctrl->phy_con1);
254 val &= ~(CTRL_GATEDURADJ_MASK);
255 writel(val, &phy1_ctrl->phy_con1);
256
257 writel(CTRL_RDLVL_GATE_ENABLE, &drex0->rdlvl_config);
258 i = TIMEOUT;
259 while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) !=
260 RDLVL_COMPLETE_CHO) && (i > 0)) {
Gabe Black607c0b62013-05-16 05:45:57 -0700261 /*
262 * TODO(waihong): Comment on how long this take to
263 * timeout
264 */
265 udelay(1);
266 i--;
267 }
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700268 if (!i)
Gabe Black607c0b62013-05-16 05:45:57 -0700269 return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700270 writel(CTRL_RDLVL_GATE_DISABLE, &drex0->rdlvl_config);
271
272 writel(CTRL_RDLVL_GATE_ENABLE, &drex1->rdlvl_config);
273 i = TIMEOUT;
274 while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) !=
275 RDLVL_COMPLETE_CHO) && (i > 0)) {
276 /*
277 * TODO(waihong): Comment on how long this take to
278 * timeout
279 */
280 udelay(1);
281 i--;
Gabe Black607c0b62013-05-16 05:45:57 -0700282 }
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700283 if (!i)
284 return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
285 writel(CTRL_RDLVL_GATE_DISABLE, &drex1->rdlvl_config);
Gabe Black607c0b62013-05-16 05:45:57 -0700286
287 writel(0, &phy0_ctrl->phy_con14);
288 writel(0, &phy1_ctrl->phy_con14);
289
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700290 writel(0x00030000, &drex0->directcmd);
291 writel(0x00130000, &drex0->directcmd);
292 writel(0x00030000, &drex1->directcmd);
293 writel(0x00130000, &drex1->directcmd);
Gabe Black607c0b62013-05-16 05:45:57 -0700294
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700295 /* Set Read DQ Calibration */
296 writel(0x00030004, &drex0->directcmd);
297 writel(0x00130004, &drex0->directcmd);
298 writel(0x00030004, &drex1->directcmd);
299 writel(0x00130004, &drex1->directcmd);
300
301 val = readl(&phy0_ctrl->phy_con1);
302 val |= READ_LEVELLING_DDR3;
303 writel(val, &phy0_ctrl->phy_con1);
304 val = readl(&phy1_ctrl->phy_con1);
305 val |= READ_LEVELLING_DDR3;
306 writel(val, &phy1_ctrl->phy_con1);
307
308 val = readl(&phy0_ctrl->phy_con2);
309 val |= (RDLVL_EN | RDLVL_INCR_ADJ);
310 writel(val, &phy0_ctrl->phy_con2);
311 val = readl(&phy1_ctrl->phy_con2);
312 val |= (RDLVL_EN | RDLVL_INCR_ADJ);
313 writel(val, &phy1_ctrl->phy_con2);
314
315 setbits_le32(&drex0->rdlvl_config, CTRL_RDLVL_DATA_ENABLE);
316 i = TIMEOUT;
317 while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) !=
318 RDLVL_COMPLETE_CHO) && (i > 0)) {
319 /*
320 * TODO(waihong): Comment on how long this take to
321 * timeout
322 */
323 udelay(1);
324 i--;
325 }
326 if (!i)
327 return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
328 clrbits_le32(&drex0->rdlvl_config, CTRL_RDLVL_DATA_ENABLE);
329
330 setbits_le32(&drex1->rdlvl_config, CTRL_RDLVL_DATA_ENABLE);
331 i = TIMEOUT;
332 while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) !=
333 RDLVL_COMPLETE_CHO) && (i > 0)) {
334 /*
335 * TODO(waihong): Comment on how long this take to
336 * timeout
337 */
338 udelay(1);
339 i--;
340 }
341 if (!i)
342 return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
343 clrbits_le32(&drex1->rdlvl_config, CTRL_RDLVL_DATA_ENABLE);
344
345 writel(0x00030000, &drex0->directcmd);
346 writel(0x00130000, &drex0->directcmd);
347 writel(0x00030000, &drex1->directcmd);
348 writel(0x00130000, &drex1->directcmd);
349
350 update_reset_dll(drex0, DDR_MODE_DDR3);
351 update_reset_dll(drex1, DDR_MODE_DDR3);
352
353 /* Common Settings for Leveling */
354 val = PHY_CON12_RESET_VAL;
355 writel((val + nLockW_phy0), &phy0_ctrl->phy_con12);
356 writel((val + nLockW_phy1), &phy1_ctrl->phy_con12);
357
358 setbits_le32(&phy0_ctrl->phy_con2, DLL_DESKEW_EN);
359 setbits_le32(&phy1_ctrl->phy_con2, DLL_DESKEW_EN);
360
361 update_reset_dll(drex0, DDR_MODE_DDR3);
362 update_reset_dll(drex1, DDR_MODE_DDR3);
Gabe Black607c0b62013-05-16 05:45:57 -0700363 }
364
365 /* Send PALL command */
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700366 dmc_config_prech(mem, drex0);
367 dmc_config_prech(mem, drex1);
Gabe Black607c0b62013-05-16 05:45:57 -0700368
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700369 writel(mem->memcontrol, &drex0->memcontrol);
370 writel(mem->memcontrol, &drex1->memcontrol);
Gabe Black607c0b62013-05-16 05:45:57 -0700371
372 /* Set DMC Concontrol and enable auto-refresh counter */
Ronald G. Minniche6af9292013-06-03 13:03:50 -0700373 writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) |
374 (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
375 &drex0->concontrol);
376 writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) |
377 (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
378 &drex1->concontrol);
Gabe Black607c0b62013-05-16 05:45:57 -0700379 return 0;
380}