blob: dc79d1c8ba3e559844937238e4768804d3e15692 [file] [log] [blame]
Ian Campbell2f1afcc2014-05-05 11:52:25 +01001/*
2 * sunxi DRAM controller initialization
3 * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
4 * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
5 *
6 * Based on sun4i Linux kernel sources mach-sunxi/pm/standby/dram*.c
7 * and earlier U-Boot Allwiner A10 SPL work
8 *
9 * (C) Copyright 2007-2012
10 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
11 * Berg Xing <bergxing@allwinnertech.com>
12 * Tom Cubie <tangliang@allwinnertech.com>
13 *
14 * SPDX-License-Identifier: GPL-2.0+
15 */
16
17/*
18 * Unfortunately the only documentation we have on the sun7i DRAM
19 * controller is Allwinner boot0 + boot1 code, and that code uses
20 * magic numbers & shifts with no explanations. Hence this code is
21 * rather undocumented and full of magic.
22 */
23
24#include <common.h>
25#include <asm/io.h>
26#include <asm/arch/clock.h>
27#include <asm/arch/dram.h>
28#include <asm/arch/timer.h>
29#include <asm/arch/sys_proto.h>
30
31#define CPU_CFG_CHIP_VER(n) ((n) << 6)
32#define CPU_CFG_CHIP_VER_MASK CPU_CFG_CHIP_VER(0x3)
33#define CPU_CFG_CHIP_REV_A 0x0
34#define CPU_CFG_CHIP_REV_C1 0x1
35#define CPU_CFG_CHIP_REV_C2 0x2
36#define CPU_CFG_CHIP_REV_B 0x3
37
38/*
39 * Wait up to 1s for mask to be clear in given reg.
40 */
41static void await_completion(u32 *reg, u32 mask)
42{
43 unsigned long tmo = timer_get_us() + 1000000;
44
45 while (readl(reg) & mask) {
46 if (timer_get_us() > tmo)
47 panic("Timeout initialising DRAM\n");
48 }
49}
50
51static void mctl_ddr3_reset(void)
52{
53 struct sunxi_dram_reg *dram =
54 (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
55
Hans de Goede3ab9c232014-06-09 11:36:57 +020056#ifdef CONFIG_SUN4I
57 struct sunxi_timer_reg *timer =
58 (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
59 u32 reg_val;
60
61 writel(0, &timer->cpu_cfg);
62 reg_val = readl(&timer->cpu_cfg);
63
64 if ((reg_val & CPU_CFG_CHIP_VER_MASK) !=
65 CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) {
66 setbits_le32(&dram->mcr, DRAM_MCR_RESET);
67 udelay(2);
68 clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
69 } else
70#endif
71 {
72 clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
73 udelay(2);
74 setbits_le32(&dram->mcr, DRAM_MCR_RESET);
75 }
Ian Campbell2f1afcc2014-05-05 11:52:25 +010076}
77
78static void mctl_set_drive(void)
79{
80 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
81
Hans de Goede3ab9c232014-06-09 11:36:57 +020082#ifdef CONFIG_SUN7I
Ian Campbell2f1afcc2014-05-05 11:52:25 +010083 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
Hans de Goede3ab9c232014-06-09 11:36:57 +020084#else
85 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3),
86#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +010087 DRAM_MCR_MODE_EN(0x3) |
88 0xffc);
89}
90
91static void mctl_itm_disable(void)
92{
93 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
94
95 clrsetbits_le32(&dram->ccr, DRAM_CCR_INIT, DRAM_CCR_ITM_OFF);
96}
97
98static void mctl_itm_enable(void)
99{
100 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
101
102 clrbits_le32(&dram->ccr, DRAM_CCR_ITM_OFF);
103}
104
105static void mctl_enable_dll0(u32 phase)
106{
107 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
108
109 clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
110 ((phase >> 16) & 0x3f) << 6);
111 clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE);
112 udelay(2);
113
114 clrbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET | DRAM_DLLCR_DISABLE);
115 udelay(22);
116
117 clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_DISABLE, DRAM_DLLCR_NRESET);
118 udelay(22);
119}
120
121/*
122 * Note: This differs from pm/standby in that it checks the bus width
123 */
124static void mctl_enable_dllx(u32 phase)
125{
126 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
127 u32 i, n, bus_width;
128
129 bus_width = readl(&dram->dcr);
130
131 if ((bus_width & DRAM_DCR_BUS_WIDTH_MASK) ==
132 DRAM_DCR_BUS_WIDTH(DRAM_DCR_BUS_WIDTH_32BIT))
133 n = DRAM_DCR_NR_DLLCR_32BIT;
134 else
135 n = DRAM_DCR_NR_DLLCR_16BIT;
136
137 for (i = 1; i < n; i++) {
138 clrsetbits_le32(&dram->dllcr[i], 0xf << 14,
139 (phase & 0xf) << 14);
140 clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET,
141 DRAM_DLLCR_DISABLE);
142 phase >>= 4;
143 }
144 udelay(2);
145
146 for (i = 1; i < n; i++)
147 clrbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET |
148 DRAM_DLLCR_DISABLE);
149 udelay(22);
150
151 for (i = 1; i < n; i++)
152 clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_DISABLE,
153 DRAM_DLLCR_NRESET);
154 udelay(22);
155}
156
157static u32 hpcr_value[32] = {
Hans de Goede8c1c7822014-06-09 11:36:58 +0200158#ifdef CONFIG_SUN5I
159 0, 0, 0, 0,
160 0, 0, 0, 0,
161 0, 0, 0, 0,
162 0, 0, 0, 0,
163 0x1031, 0x1031, 0x0735, 0x1035,
164 0x1035, 0x0731, 0x1031, 0,
165 0x0301, 0x0301, 0x0301, 0x0301,
166 0x0301, 0x0301, 0x0301, 0
167#endif
Hans de Goede3ab9c232014-06-09 11:36:57 +0200168#ifdef CONFIG_SUN4I
169 0x0301, 0x0301, 0x0301, 0x0301,
170 0x0301, 0x0301, 0, 0,
171 0, 0, 0, 0,
172 0, 0, 0, 0,
173 0x1031, 0x1031, 0x0735, 0x5031,
174 0x1035, 0x0731, 0x1031, 0x0735,
175 0x1035, 0x1031, 0x0731, 0x1035,
176 0x1031, 0x0301, 0x0301, 0x0731
177#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100178#ifdef CONFIG_SUN7I
179 0x0301, 0x0301, 0x0301, 0x0301,
180 0x0301, 0x0301, 0x0301, 0x0301,
181 0, 0, 0, 0,
182 0, 0, 0, 0,
183 0x1031, 0x1031, 0x0735, 0x1035,
184 0x1035, 0x0731, 0x1031, 0x0735,
185 0x1035, 0x1031, 0x0731, 0x1035,
186 0x0001, 0x1031, 0, 0x1031
187 /* last row differs from boot0 source table
188 * 0x1031, 0x0301, 0x0301, 0x0731
189 * but boot0 code skips #28 and #30, and sets #29 and #31 to the
190 * value from #28 entry (0x1031)
191 */
192#endif
193};
194
195static void mctl_configure_hostport(void)
196{
197 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
198 u32 i;
199
200 for (i = 0; i < 32; i++)
201 writel(hpcr_value[i], &dram->hpcr[i]);
202}
203
204static void mctl_setup_dram_clock(u32 clk)
205{
206 u32 reg_val;
207 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
208
209 /* setup DRAM PLL */
210 reg_val = readl(&ccm->pll5_cfg);
211 reg_val &= ~CCM_PLL5_CTRL_M_MASK; /* set M to 0 (x1) */
212 reg_val &= ~CCM_PLL5_CTRL_K_MASK; /* set K to 0 (x1) */
213 reg_val &= ~CCM_PLL5_CTRL_N_MASK; /* set N to 0 (x0) */
214 reg_val &= ~CCM_PLL5_CTRL_P_MASK; /* set P to 0 (x1) */
215 if (clk >= 540 && clk < 552) {
216 /* dram = 540MHz, pll5p = 540MHz */
217 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
218 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
219 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(15));
220 reg_val |= CCM_PLL5_CTRL_P(1);
221 } else if (clk >= 512 && clk < 528) {
222 /* dram = 512MHz, pll5p = 384MHz */
223 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
224 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(4));
225 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(16));
226 reg_val |= CCM_PLL5_CTRL_P(2);
227 } else if (clk >= 496 && clk < 504) {
228 /* dram = 496MHz, pll5p = 372MHz */
229 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
230 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
231 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(31));
232 reg_val |= CCM_PLL5_CTRL_P(2);
233 } else if (clk >= 468 && clk < 480) {
234 /* dram = 468MHz, pll5p = 468MHz */
235 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
236 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
237 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(13));
238 reg_val |= CCM_PLL5_CTRL_P(1);
239 } else if (clk >= 396 && clk < 408) {
240 /* dram = 396MHz, pll5p = 396MHz */
241 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
242 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
243 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(11));
244 reg_val |= CCM_PLL5_CTRL_P(1);
245 } else {
246 /* any other frequency that is a multiple of 24 */
247 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
248 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
249 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(clk / 24));
250 reg_val |= CCM_PLL5_CTRL_P(CCM_PLL5_CTRL_P_X(2));
251 }
252 reg_val &= ~CCM_PLL5_CTRL_VCO_GAIN; /* PLL VCO Gain off */
253 reg_val |= CCM_PLL5_CTRL_EN; /* PLL On */
254 writel(reg_val, &ccm->pll5_cfg);
255 udelay(5500);
256
257 setbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_DDR_CLK);
258
259#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I)
260 /* reset GPS */
261 clrbits_le32(&ccm->gps_clk_cfg, CCM_GPS_CTRL_RESET | CCM_GPS_CTRL_GATE);
262 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
263 udelay(1);
264 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
265#endif
266
Hans de Goede3ab9c232014-06-09 11:36:57 +0200267#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100268 /* setup MBUS clock */
269 reg_val = CCM_MBUS_CTRL_GATE |
Hans de Goede8c1c7822014-06-09 11:36:58 +0200270#ifdef CONFIG_SUN7I
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100271 CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
272 CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) |
273 CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
Hans de Goede8c1c7822014-06-09 11:36:58 +0200274#else /* defined(CONFIG_SUN5I) */
275 CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) |
276 CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
277 CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
278#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100279 writel(reg_val, &ccm->mbus_clk_cfg);
Hans de Goede3ab9c232014-06-09 11:36:57 +0200280#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100281
282 /*
283 * open DRAMC AHB & DLL register clock
284 * close it first
285 */
Hans de Goede3ab9c232014-06-09 11:36:57 +0200286#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100287 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
Hans de Goede3ab9c232014-06-09 11:36:57 +0200288#else
289 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
290#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100291 udelay(22);
292
293 /* then open it */
Hans de Goede3ab9c232014-06-09 11:36:57 +0200294#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100295 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
Hans de Goede3ab9c232014-06-09 11:36:57 +0200296#else
297 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
298#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100299 udelay(22);
300}
301
302static int dramc_scan_readpipe(void)
303{
304 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
305 u32 reg_val;
306
307 /* data training trigger */
308#ifdef CONFIG_SUN7I
309 clrbits_le32(&dram->csr, DRAM_CSR_FAILED);
310#endif
311 setbits_le32(&dram->ccr, DRAM_CCR_DATA_TRAINING);
312
313 /* check whether data training process has completed */
314 await_completion(&dram->ccr, DRAM_CCR_DATA_TRAINING);
315
316 /* check data training result */
317 reg_val = readl(&dram->csr);
318 if (reg_val & DRAM_CSR_FAILED)
319 return -1;
320
321 return 0;
322}
323
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100324static void dramc_clock_output_en(u32 on)
325{
326#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
327 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
328
329 if (on)
330 setbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
331 else
332 clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
333#endif
Hans de Goede3ab9c232014-06-09 11:36:57 +0200334#ifdef CONFIG_SUN4I
335 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
336 if (on)
337 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
338 else
339 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
340#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100341}
342
343static const u16 tRFC_table[2][6] = {
344 /* 256Mb 512Mb 1Gb 2Gb 4Gb 8Gb */
345 /* DDR2 75ns 105ns 127.5ns 195ns 327.5ns invalid */
346 { 77, 108, 131, 200, 336, 336 },
347 /* DDR3 invalid 90ns 110ns 160ns 300ns 350ns */
348 { 93, 93, 113, 164, 308, 359 }
349};
350
351static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
352{
353 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
354 u32 tRFC, tREFI;
355
356 tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
357 tREFI = (7987 * clk) >> 10; /* <= 7.8us */
358
359 writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr);
360}
361
Siarhei Siamashka551bfb92014-08-03 05:32:40 +0300362/*
363 * If the dram->ppwrsctl (SDR_DPCR) register has the lowest bit set to 1, this
364 * means that DRAM is currently in self-refresh mode and retaining the old
365 * data. Since we have no idea what to do in this situation yet, just set this
366 * register to 0 and initialize DRAM in the same way as on any normal reboot
367 * (discarding whatever was stored there).
368 *
369 * Note: on sun7i hardware, the highest 16 bits need to be set to 0x1651 magic
370 * value for this write operation to have any effect. On sun5i hadware this
371 * magic value is not necessary. And on sun4i hardware the writes to this
372 * register seem to have no effect at all.
373 */
374static void mctl_disable_power_save(void)
375{
376 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
377 writel(0x16510000, &dram->ppwrsctl);
378}
379
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100380unsigned long dramc_init(struct dram_para *para)
381{
382 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
383 u32 reg_val;
384 u32 density;
385 int ret_val;
386
387 /* check input dram parameter structure */
388 if (!para)
389 return 0;
390
391 /* setup DRAM relative clock */
392 mctl_setup_dram_clock(para->clock);
393
Hans de Goede8c1c7822014-06-09 11:36:58 +0200394 /* Disable any pad power save control */
Siarhei Siamashka551bfb92014-08-03 05:32:40 +0300395 mctl_disable_power_save();
Hans de Goede8c1c7822014-06-09 11:36:58 +0200396
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100397 /* reset external DRAM */
Hans de Goede3ab9c232014-06-09 11:36:57 +0200398#ifndef CONFIG_SUN7I
399 mctl_ddr3_reset();
400#endif
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100401 mctl_set_drive();
402
403 /* dram clock off */
404 dramc_clock_output_en(0);
405
Hans de Goede3ab9c232014-06-09 11:36:57 +0200406#ifdef CONFIG_SUN4I
407 /* select dram controller 1 */
408 writel(DRAM_CSEL_MAGIC, &dram->csel);
409#endif
410
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100411 mctl_itm_disable();
412 mctl_enable_dll0(para->tpr3);
413
414 /* configure external DRAM */
415 reg_val = 0x0;
416 if (para->type == DRAM_MEMORY_TYPE_DDR3)
417 reg_val |= DRAM_DCR_TYPE_DDR3;
418 reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);
419
420 if (para->density == 256)
421 density = DRAM_DCR_CHIP_DENSITY_256M;
422 else if (para->density == 512)
423 density = DRAM_DCR_CHIP_DENSITY_512M;
424 else if (para->density == 1024)
425 density = DRAM_DCR_CHIP_DENSITY_1024M;
426 else if (para->density == 2048)
427 density = DRAM_DCR_CHIP_DENSITY_2048M;
428 else if (para->density == 4096)
429 density = DRAM_DCR_CHIP_DENSITY_4096M;
430 else if (para->density == 8192)
431 density = DRAM_DCR_CHIP_DENSITY_8192M;
432 else
433 density = DRAM_DCR_CHIP_DENSITY_256M;
434
435 reg_val |= DRAM_DCR_CHIP_DENSITY(density);
436 reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
437 reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
438 reg_val |= DRAM_DCR_CMD_RANK_ALL;
439 reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE);
440 writel(reg_val, &dram->dcr);
441
442#ifdef CONFIG_SUN7I
443 setbits_le32(&dram->zqcr1, (0x1 << 24) | (0x1 << 1));
444 if (para->tpr4 & 0x2)
445 clrsetbits_le32(&dram->zqcr1, (0x1 << 24), (0x1 << 1));
446 dramc_clock_output_en(1);
447#endif
448
449#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
450 /* set odt impendance divide ratio */
451 reg_val = ((para->zq) >> 8) & 0xfffff;
452 reg_val |= ((para->zq) & 0xff) << 20;
453 reg_val |= (para->zq) & 0xf0000000;
454 writel(reg_val, &dram->zqcr0);
455#endif
456
457#ifdef CONFIG_SUN7I
458 /* Set CKE Delay to about 1ms */
459 setbits_le32(&dram->idcr, 0x1ffff);
460#endif
461
462#ifdef CONFIG_SUN7I
Siarhei Siamashka551bfb92014-08-03 05:32:40 +0300463 mctl_ddr3_reset();
Hans de Goede3ab9c232014-06-09 11:36:57 +0200464#else
465 /* dram clock on */
466 dramc_clock_output_en(1);
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100467#endif
468
469 udelay(1);
470
471 await_completion(&dram->ccr, DRAM_CCR_INIT);
472
473 mctl_enable_dllx(para->tpr3);
474
Hans de Goede3ab9c232014-06-09 11:36:57 +0200475#ifdef CONFIG_SUN4I
476 /* set odt impedance divide ratio */
477 reg_val = ((para->zq) >> 8) & 0xfffff;
478 reg_val |= ((para->zq) & 0xff) << 20;
479 reg_val |= (para->zq) & 0xf0000000;
480 writel(reg_val, &dram->zqcr0);
481#endif
482
483#ifdef CONFIG_SUN4I
484 /* set I/O configure register */
485 reg_val = 0x00cc0000;
486 reg_val |= (para->odt_en) & 0x3;
487 reg_val |= ((para->odt_en) & 0x3) << 30;
488 writel(reg_val, &dram->iocr);
489#endif
490
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100491 /* set refresh period */
492 dramc_set_autorefresh_cycle(para->clock, para->type - 2, density);
493
494 /* set timing parameters */
495 writel(para->tpr0, &dram->tpr0);
496 writel(para->tpr1, &dram->tpr1);
497 writel(para->tpr2, &dram->tpr2);
498
499 if (para->type == DRAM_MEMORY_TYPE_DDR3) {
500 reg_val = DRAM_MR_BURST_LENGTH(0x0);
501#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
502 reg_val |= DRAM_MR_POWER_DOWN;
503#endif
504 reg_val |= DRAM_MR_CAS_LAT(para->cas - 4);
505 reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
506 } else if (para->type == DRAM_MEMORY_TYPE_DDR2) {
507 reg_val = DRAM_MR_BURST_LENGTH(0x2);
508 reg_val |= DRAM_MR_CAS_LAT(para->cas);
509 reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
510 }
511 writel(reg_val, &dram->mr);
512
513 writel(para->emr1, &dram->emr);
514 writel(para->emr2, &dram->emr2);
515 writel(para->emr3, &dram->emr3);
516
517 /* set DQS window mode */
518 clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE);
519
520#ifdef CONFIG_SUN7I
521 /* Command rate timing mode 2T & 1T */
522 if (para->tpr4 & 0x1)
523 setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T);
524#endif
525 /* reset external DRAM */
526 setbits_le32(&dram->ccr, DRAM_CCR_INIT);
527 await_completion(&dram->ccr, DRAM_CCR_INIT);
528
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100529 /* scan read pipe value */
530 mctl_itm_enable();
Siarhei Siamashka27942f12014-08-03 05:32:39 +0300531 ret_val = dramc_scan_readpipe();
Ian Campbell2f1afcc2014-05-05 11:52:25 +0100532
533 if (ret_val < 0)
534 return 0;
535
536 /* configure all host port */
537 mctl_configure_hostport();
538
539 return get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
540}