]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/samsung/smdk5250/dmc_init.c
ext4: cache-align buffers so the invalidation works
[people/ms/u-boot.git] / board / samsung / smdk5250 / dmc_init.c
CommitLineData
0aee53ba
CK
1/*
2 * Memory setup for SMDK5250 board based on EXYNOS5
3 *
4 * Copyright (C) 2012 Samsung Electronics
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
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.
13 *
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.
18 *
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,
22 * MA 02111-1307 USA
23 */
24
25#include <config.h>
26#include <asm/io.h>
27#include <asm/arch/dmc.h>
28#include <asm/arch/clock.h>
29#include <asm/arch/cpu.h>
30#include "setup.h"
31
32/* APLL : 1GHz */
33/* MCLK_CDREX: MCLK_CDREX_533*/
34/* LPDDR support: LPDDR2 */
35static void reset_phy_ctrl(void);
36static void config_zq(struct exynos5_phy_control *,
37 struct exynos5_phy_control *);
38static void update_reset_dll(struct exynos5_dmc *);
39static void config_cdrex(void);
40static void config_mrs(struct exynos5_dmc *);
41static void sec_sdram_phy_init(struct exynos5_dmc *);
42static void config_prech(struct exynos5_dmc *);
43static void config_rdlvl(struct exynos5_dmc *,
44 struct exynos5_phy_control *,
45 struct exynos5_phy_control *);
46static void config_memory(struct exynos5_dmc *);
47
48static void config_offsets(unsigned int,
49 struct exynos5_phy_control *,
50 struct exynos5_phy_control *);
51
52static void reset_phy_ctrl(void)
53{
54 struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
55
56 writel(PHY_RESET_VAL, &clk->lpddr3phy_ctrl);
57 sdelay(0x10000);
58}
59
60static void config_zq(struct exynos5_phy_control *phy0_ctrl,
61 struct exynos5_phy_control *phy1_ctrl)
62{
63 unsigned long val = 0;
64 /*
65 * ZQ Calibration:
66 * Select Driver Strength,
67 * long calibration for manual calibration
68 */
69 val = PHY_CON16_RESET_VAL;
70 SET_ZQ_MODE_DDS_VAL(val);
71 SET_ZQ_MODE_TERM_VAL(val);
72 val |= ZQ_CLK_DIV_EN;
73 writel(val, &phy0_ctrl->phy_con16);
74 writel(val, &phy1_ctrl->phy_con16);
75
76 /* Disable termination */
77 val |= ZQ_MODE_NOTERM;
78 writel(val, &phy0_ctrl->phy_con16);
79 writel(val, &phy1_ctrl->phy_con16);
80
81 /* ZQ_MANUAL_START: Enable */
82 val |= ZQ_MANUAL_STR;
83 writel(val, &phy0_ctrl->phy_con16);
84 writel(val, &phy1_ctrl->phy_con16);
85 sdelay(0x10000);
86
87 /* ZQ_MANUAL_START: Disable */
88 val &= ~ZQ_MANUAL_STR;
89 writel(val, &phy0_ctrl->phy_con16);
90 writel(val, &phy1_ctrl->phy_con16);
91}
92
93static void update_reset_dll(struct exynos5_dmc *dmc)
94{
95 unsigned long val;
96 /*
97 * Update DLL Information:
98 * Force DLL Resyncronization
99 */
100 val = readl(&dmc->phycontrol0);
101 val |= FP_RSYNC;
102 writel(val, &dmc->phycontrol0);
103
104 /* Reset Force DLL Resyncronization */
105 val = readl(&dmc->phycontrol0);
106 val &= ~FP_RSYNC;
107 writel(val, &dmc->phycontrol0);
108}
109
110static void config_mrs(struct exynos5_dmc *dmc)
111{
112 unsigned long channel, chip, mask = 0, val;
113
114 for (channel = 0; channel < CONFIG_DMC_CHANNELS; channel++) {
115 SET_CMD_CHANNEL(mask, channel);
116 for (chip = 0; chip < CONFIG_CHIPS_PER_CHANNEL; chip++) {
117 /*
118 * NOP CMD:
119 * Assert and hold CKE to logic high level
120 */
121 SET_CMD_CHIP(mask, chip);
122 val = DIRECT_CMD_NOP | mask;
123 writel(val, &dmc->directcmd);
124 sdelay(0x10000);
125
126 /* EMRS, MRS Cmds(Mode Reg Settings) Using Direct Cmd */
127 val = DIRECT_CMD_MRS1 | mask;
128 writel(val, &dmc->directcmd);
129 sdelay(0x10000);
130
131 val = DIRECT_CMD_MRS2 | mask;
132 writel(val, &dmc->directcmd);
133 sdelay(0x10000);
134
135 /* MCLK_CDREX_533 */
136 val = DIRECT_CMD_MRS3 | mask;
137 writel(val, &dmc->directcmd);
138 sdelay(0x10000);
139
140 val = DIRECT_CMD_MRS4 | mask;
141 writel(val, &dmc->directcmd);
142 sdelay(0x10000);
143 }
144 }
145}
146
147static void config_prech(struct exynos5_dmc *dmc)
148{
149 unsigned long channel, chip, mask = 0, val;
150
151 for (channel = 0; channel < CONFIG_DMC_CHANNELS; channel++) {
152 SET_CMD_CHANNEL(mask, channel);
153 for (chip = 0; chip < CONFIG_CHIPS_PER_CHANNEL; chip++) {
154 SET_CMD_CHIP(mask, chip);
155 /* PALL (all banks precharge) CMD */
156 val = DIRECT_CMD_PALL | mask;
157 writel(val, &dmc->directcmd);
158 sdelay(0x10000);
159 }
160 }
161}
162
163static void sec_sdram_phy_init(struct exynos5_dmc *dmc)
164{
165 unsigned long val;
166 val = readl(&dmc->concontrol);
167 val |= DFI_INIT_START;
168 writel(val, &dmc->concontrol);
169 sdelay(0x10000);
170
171 val = readl(&dmc->concontrol);
172 val &= ~DFI_INIT_START;
173 writel(val, &dmc->concontrol);
174}
175
176static void config_offsets(unsigned int state,
177 struct exynos5_phy_control *phy0_ctrl,
178 struct exynos5_phy_control *phy1_ctrl)
179{
180 unsigned long val;
181 /* Set Offsets to read DQS */
182 val = (state == SET) ? SET_DQS_OFFSET_VAL : RESET_DQS_OFFSET_VAL;
183 writel(val, &phy0_ctrl->phy_con4);
184 writel(val, &phy1_ctrl->phy_con4);
185
186 /* Set Offsets to read DQ */
187 val = (state == SET) ? SET_DQ_OFFSET_VAL : RESET_DQ_OFFSET_VAL;
188 writel(val, &phy0_ctrl->phy_con6);
189 writel(val, &phy1_ctrl->phy_con6);
190
191 /* Debug Offset */
192 val = (state == SET) ? SET_DEBUG_OFFSET_VAL : RESET_DEBUG_OFFSET_VAL;
193 writel(val, &phy0_ctrl->phy_con10);
194 writel(val, &phy1_ctrl->phy_con10);
195}
196
197static void config_cdrex(void)
198{
199 struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
200 writel(CLK_DIV_CDREX_VAL, &clk->div_cdrex);
201 writel(CLK_SRC_CDREX_VAL, &clk->src_cdrex);
202 sdelay(0x30000);
203}
204
205static void config_ctrl_dll_on(unsigned int state,
206 unsigned int ctrl_force_val,
207 struct exynos5_phy_control *phy0_ctrl,
208 struct exynos5_phy_control *phy1_ctrl)
209{
210 unsigned long val;
211 val = readl(&phy0_ctrl->phy_con12);
212 CONFIG_CTRL_DLL_ON(val, state);
213 SET_CTRL_FORCE_VAL(val, ctrl_force_val);
214 writel(val, &phy0_ctrl->phy_con12);
215
216 val = readl(&phy1_ctrl->phy_con12);
217 CONFIG_CTRL_DLL_ON(val, state);
218 SET_CTRL_FORCE_VAL(val, ctrl_force_val);
219 writel(val, &phy1_ctrl->phy_con12);
220}
221
222static void config_ctrl_start(unsigned int state,
223 struct exynos5_phy_control *phy0_ctrl,
224 struct exynos5_phy_control *phy1_ctrl)
225{
226 unsigned long val;
227 val = readl(&phy0_ctrl->phy_con12);
228 CONFIG_CTRL_START(val, state);
229 writel(val, &phy0_ctrl->phy_con12);
230
231 val = readl(&phy1_ctrl->phy_con12);
232 CONFIG_CTRL_START(val, state);
233 writel(val, &phy1_ctrl->phy_con12);
234}
235
236#if defined(CONFIG_RD_LVL)
237static void config_rdlvl(struct exynos5_dmc *dmc,
238 struct exynos5_phy_control *phy0_ctrl,
239 struct exynos5_phy_control *phy1_ctrl)
240{
241 unsigned long val;
242
243 /* Disable CTRL_DLL_ON and set ctrl_force */
244 config_ctrl_dll_on(RESET, 0x2D, phy0_ctrl, phy1_ctrl);
245
246 /*
247 * Set ctrl_gateadj, ctrl_readadj
248 * ctrl_gateduradj, rdlvl_pass_adj
249 * rdlvl_rddataPadj
250 */
251 val = SET_RDLVL_RDDATAPADJ;
252 writel(val, &phy0_ctrl->phy_con1);
253 writel(val, &phy1_ctrl->phy_con1);
254
255 /* LPDDR2 Address */
256 writel(LPDDR2_ADDR, &phy0_ctrl->phy_con22);
257 writel(LPDDR2_ADDR, &phy1_ctrl->phy_con22);
258
259 /* Enable Byte Read Leveling set ctrl_ddr_mode */
260 val = readl(&phy0_ctrl->phy_con0);
261 val |= BYTE_RDLVL_EN;
262 writel(val, &phy0_ctrl->phy_con0);
263 val = readl(&phy1_ctrl->phy_con0);
264 val |= BYTE_RDLVL_EN;
265 writel(val, &phy1_ctrl->phy_con0);
266
267 /* rdlvl_en: Use levelling offset instead ctrl_shiftc */
268 val = PHY_CON2_RESET_VAL | RDLVL_EN;
269 writel(val, &phy0_ctrl->phy_con2);
270 writel(val, &phy1_ctrl->phy_con2);
271 sdelay(0x10000);
272
273 /* Enable Data Eye Training */
274 val = readl(&dmc->rdlvl_config);
275 val |= CTRL_RDLVL_DATA_EN;
276 writel(val, &dmc->rdlvl_config);
277 sdelay(0x10000);
278
279 /* Disable Data Eye Training */
280 val = readl(&dmc->rdlvl_config);
281 val &= ~CTRL_RDLVL_DATA_EN;
282 writel(val, &dmc->rdlvl_config);
283
284 /* RdDeSkew_clear: Clear */
285 val = readl(&phy0_ctrl->phy_con2);
286 val |= RDDSKEW_CLEAR;
287 writel(val, &phy0_ctrl->phy_con2);
288 val = readl(&phy1_ctrl->phy_con2);
289 val |= RDDSKEW_CLEAR;
290 writel(val, &phy1_ctrl->phy_con2);
291
292 /* Enable CTRL_DLL_ON */
293 config_ctrl_dll_on(SET, 0x0, phy0_ctrl, phy1_ctrl);
294
295 update_reset_dll(dmc);
296 sdelay(0x10000);
297
298 /* ctrl_atgte: ctrl_gate_p*, ctrl_read_p* generated by PHY */
299 val = readl(&phy0_ctrl->phy_con0);
300 val &= ~CTRL_ATGATE;
301 writel(val, &phy0_ctrl->phy_con0);
302 val = readl(&phy1_ctrl->phy_con0);
303 val &= ~CTRL_ATGATE;
304 writel(val, &phy1_ctrl->phy_con0);
305}
306#endif
307
308static void config_memory(struct exynos5_dmc *dmc)
309{
310 /*
311 * Memory Configuration Chip 0
312 * Address Mapping: Interleaved
313 * Number of Column address Bits: 10 bits
314 * Number of Rows Address Bits: 14
315 * Number of Banks: 8
316 */
317 writel(DMC_MEMCONFIG0_VAL, &dmc->memconfig0);
318
319 /*
320 * Memory Configuration Chip 1
321 * Address Mapping: Interleaved
322 * Number of Column address Bits: 10 bits
323 * Number of Rows Address Bits: 14
324 * Number of Banks: 8
325 */
326 writel(DMC_MEMCONFIG1_VAL, &dmc->memconfig1);
327
328 /*
329 * Chip0: AXI
330 * AXI Base Address: 0x40000000
331 * AXI Base Address Mask: 0x780
332 */
333 writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0);
334
335 /*
336 * Chip1: AXI
337 * AXI Base Address: 0x80000000
338 * AXI Base Address Mask: 0x780
339 */
340 writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1);
341}
342
343void mem_ctrl_init()
344{
345 struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
346 struct exynos5_dmc *dmc;
347 unsigned long val;
348
349 phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE;
350 phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE;
351 dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE;
352
353 /* Reset PHY Controllor: PHY_RESET[0] */
354 reset_phy_ctrl();
355
356 /*set Read Latancy and Burst Length for PHY0 and PHY1 */
357 writel(PHY_CON42_VAL, &phy0_ctrl->phy_con42);
358 writel(PHY_CON42_VAL, &phy1_ctrl->phy_con42);
359
360 /* ZQ Cofiguration */
361 config_zq(phy0_ctrl, phy1_ctrl);
362
363 /* Operation Mode : LPDDR2 */
364 val = PHY_CON0_RESET_VAL;
365 SET_CTRL_DDR_MODE(val, DDR_MODE_LPDDR2);
366 writel(val, &phy0_ctrl->phy_con0);
367 writel(val, &phy1_ctrl->phy_con0);
368
369 /* DQS, DQ: Signal, for LPDDR2: Always Set */
370 val = CTRL_PULLD_DQ | CTRL_PULLD_DQS;
371 writel(val, &phy0_ctrl->phy_con14);
372 writel(val, &phy1_ctrl->phy_con14);
373
374 /* Init SEC SDRAM PHY */
375 sec_sdram_phy_init(dmc);
376 sdelay(0x10000);
377
378 update_reset_dll(dmc);
379
380 /*
381 * Dynamic Clock: Always Running
382 * Memory Burst length: 4
383 * Number of chips: 2
384 * Memory Bus width: 32 bit
385 * Memory Type: LPDDR2-S4
386 * Additional Latancy for PLL: 1 Cycle
387 */
388 writel(DMC_MEMCONTROL_VAL, &dmc->memcontrol);
389
390 config_memory(dmc);
391
392 /* Precharge Configuration */
393 writel(DMC_PRECHCONFIG_VAL, &dmc->prechconfig);
394
395 /* Power Down mode Configuration */
396 writel(DMC_PWRDNCONFIG_VAL, &dmc->pwrdnconfig);
397
398 /* Periodic Refrese Interval */
399 writel(DMC_TIMINGREF_VAL, &dmc->timingref);
400
401 /*
402 * TimingRow, TimingData, TimingPower Setting:
403 * Values as per Memory AC Parameters
404 */
405 writel(DMC_TIMINGROW_VAL, &dmc->timingrow);
406
407 writel(DMC_TIMINGDATA_VAL, &dmc->timingdata);
408
409 writel(DMC_TIMINGPOWER_VAL, &dmc->timingpower);
410
411 /* Memory Channel Inteleaving Size: 128 Bytes */
412 writel(CONFIG_IV_SIZE, &dmc->ivcontrol);
413
414 /* Set DQS, DQ and DEBUG offsets */
415 config_offsets(SET, phy0_ctrl, phy1_ctrl);
416
417 /* Disable CTRL_DLL_ON and set ctrl_force */
418 config_ctrl_dll_on(RESET, 0x7F, phy0_ctrl, phy1_ctrl);
419 sdelay(0x10000);
420
421 update_reset_dll(dmc);
422
423 /* Config MRS(Mode Register Settingg) */
424 config_mrs(dmc);
425
426 config_cdrex();
427
428 /* Reset DQS DQ and DEBUG offsets */
429 config_offsets(RESET, phy0_ctrl, phy1_ctrl);
430
431 /* Enable CTRL_DLL_ON */
432 config_ctrl_dll_on(SET, 0x0, phy0_ctrl, phy1_ctrl);
433
434 /* Stop DLL Locking */
435 config_ctrl_start(RESET, phy0_ctrl, phy1_ctrl);
436 sdelay(0x10000);
437
438 /* Start DLL Locking */
439 config_ctrl_start(SET, phy0_ctrl, phy1_ctrl);
440 sdelay(0x10000);
441
442 update_reset_dll(dmc);
443
444#if defined(CONFIG_RD_LVL)
445 config_rdlvl(dmc, phy0_ctrl, phy1_ctrl);
446#endif
447 config_prech(dmc);
448
449 /*
450 * Dynamic Clock: Stops During Idle Period
451 * Dynamic Power Down: Enable
452 * Dynamic Self refresh: Enable
453 */
454 val = readl(&dmc->memcontrol);
455 val |= CLK_STOP_EN | DPWRDN_EN | DSREF_EN;
456 writel(val, &dmc->memcontrol);
457
458 /* Start Auto refresh */
459 val = readl(&dmc->concontrol);
460 val |= AREF_EN;
461 writel(val, &dmc->concontrol);
462}