]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/samsung/smdk5250/dmc_init.c
tx25: Use generic gpio_* calls
[karo-tx-uboot.git] / board / samsung / smdk5250 / dmc_init.c
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 */
35 static void reset_phy_ctrl(void);
36 static void config_zq(struct exynos5_phy_control *,
37                         struct exynos5_phy_control *);
38 static void update_reset_dll(struct exynos5_dmc *);
39 static void config_cdrex(void);
40 static void config_mrs(struct exynos5_dmc *);
41 static void sec_sdram_phy_init(struct exynos5_dmc *);
42 static void config_prech(struct exynos5_dmc *);
43 static void config_rdlvl(struct exynos5_dmc *,
44                         struct exynos5_phy_control *,
45                         struct exynos5_phy_control *);
46 static void config_memory(struct exynos5_dmc *);
47
48 static void config_offsets(unsigned int,
49                                 struct exynos5_phy_control *,
50                                 struct exynos5_phy_control *);
51
52 static 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
60 static 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
93 static 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
110 static 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
147 static 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
163 static 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
176 static 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
197 static 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
205 static 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
222 static 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)
237 static 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
308 static 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
343 void 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 }