blob: a632926fa73a62c24c2a89b17d65772bf13fa86f [file] [log] [blame]
Ian Campbell286c3c32014-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
Siarhei Siamashkae626d2d2014-08-03 05:32:41 +030051/*
52 * This performs the external DRAM reset by driving the RESET pin low and
53 * then high again. According to the DDR3 spec, the RESET pin needs to be
54 * kept low for at least 200 us.
55 */
Ian Campbell286c3c32014-05-05 11:52:25 +010056static void mctl_ddr3_reset(void)
57{
58 struct sunxi_dram_reg *dram =
59 (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
60
Hans de Goede745325a2014-06-09 11:36:57 +020061#ifdef CONFIG_SUN4I
62 struct sunxi_timer_reg *timer =
63 (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
64 u32 reg_val;
65
66 writel(0, &timer->cpu_cfg);
67 reg_val = readl(&timer->cpu_cfg);
68
69 if ((reg_val & CPU_CFG_CHIP_VER_MASK) !=
70 CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) {
71 setbits_le32(&dram->mcr, DRAM_MCR_RESET);
Siarhei Siamashkae626d2d2014-08-03 05:32:41 +030072 udelay(200);
Hans de Goede745325a2014-06-09 11:36:57 +020073 clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
74 } else
75#endif
76 {
77 clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
Siarhei Siamashkae626d2d2014-08-03 05:32:41 +030078 udelay(200);
Hans de Goede745325a2014-06-09 11:36:57 +020079 setbits_le32(&dram->mcr, DRAM_MCR_RESET);
80 }
Ian Campbell286c3c32014-05-05 11:52:25 +010081}
82
83static void mctl_set_drive(void)
84{
85 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
86
Hans de Goede745325a2014-06-09 11:36:57 +020087#ifdef CONFIG_SUN7I
Ian Campbell286c3c32014-05-05 11:52:25 +010088 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
Hans de Goede745325a2014-06-09 11:36:57 +020089#else
90 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3),
91#endif
Ian Campbell286c3c32014-05-05 11:52:25 +010092 DRAM_MCR_MODE_EN(0x3) |
93 0xffc);
94}
95
96static void mctl_itm_disable(void)
97{
98 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
99
100 clrsetbits_le32(&dram->ccr, DRAM_CCR_INIT, DRAM_CCR_ITM_OFF);
101}
102
103static void mctl_itm_enable(void)
104{
105 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
106
107 clrbits_le32(&dram->ccr, DRAM_CCR_ITM_OFF);
108}
109
110static void mctl_enable_dll0(u32 phase)
111{
112 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
113
114 clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
115 ((phase >> 16) & 0x3f) << 6);
116 clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE);
117 udelay(2);
118
119 clrbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET | DRAM_DLLCR_DISABLE);
120 udelay(22);
121
122 clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_DISABLE, DRAM_DLLCR_NRESET);
123 udelay(22);
124}
125
126/*
127 * Note: This differs from pm/standby in that it checks the bus width
128 */
129static void mctl_enable_dllx(u32 phase)
130{
131 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
132 u32 i, n, bus_width;
133
134 bus_width = readl(&dram->dcr);
135
136 if ((bus_width & DRAM_DCR_BUS_WIDTH_MASK) ==
137 DRAM_DCR_BUS_WIDTH(DRAM_DCR_BUS_WIDTH_32BIT))
138 n = DRAM_DCR_NR_DLLCR_32BIT;
139 else
140 n = DRAM_DCR_NR_DLLCR_16BIT;
141
142 for (i = 1; i < n; i++) {
143 clrsetbits_le32(&dram->dllcr[i], 0xf << 14,
144 (phase & 0xf) << 14);
145 clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET,
146 DRAM_DLLCR_DISABLE);
147 phase >>= 4;
148 }
149 udelay(2);
150
151 for (i = 1; i < n; i++)
152 clrbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET |
153 DRAM_DLLCR_DISABLE);
154 udelay(22);
155
156 for (i = 1; i < n; i++)
157 clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_DISABLE,
158 DRAM_DLLCR_NRESET);
159 udelay(22);
160}
161
162static u32 hpcr_value[32] = {
Hans de Goedef84269c2014-06-09 11:36:58 +0200163#ifdef CONFIG_SUN5I
164 0, 0, 0, 0,
165 0, 0, 0, 0,
166 0, 0, 0, 0,
167 0, 0, 0, 0,
168 0x1031, 0x1031, 0x0735, 0x1035,
169 0x1035, 0x0731, 0x1031, 0,
170 0x0301, 0x0301, 0x0301, 0x0301,
171 0x0301, 0x0301, 0x0301, 0
172#endif
Hans de Goede745325a2014-06-09 11:36:57 +0200173#ifdef CONFIG_SUN4I
174 0x0301, 0x0301, 0x0301, 0x0301,
175 0x0301, 0x0301, 0, 0,
176 0, 0, 0, 0,
177 0, 0, 0, 0,
178 0x1031, 0x1031, 0x0735, 0x5031,
179 0x1035, 0x0731, 0x1031, 0x0735,
180 0x1035, 0x1031, 0x0731, 0x1035,
181 0x1031, 0x0301, 0x0301, 0x0731
182#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100183#ifdef CONFIG_SUN7I
184 0x0301, 0x0301, 0x0301, 0x0301,
185 0x0301, 0x0301, 0x0301, 0x0301,
186 0, 0, 0, 0,
187 0, 0, 0, 0,
188 0x1031, 0x1031, 0x0735, 0x1035,
189 0x1035, 0x0731, 0x1031, 0x0735,
190 0x1035, 0x1031, 0x0731, 0x1035,
191 0x0001, 0x1031, 0, 0x1031
192 /* last row differs from boot0 source table
193 * 0x1031, 0x0301, 0x0301, 0x0731
194 * but boot0 code skips #28 and #30, and sets #29 and #31 to the
195 * value from #28 entry (0x1031)
196 */
197#endif
198};
199
200static void mctl_configure_hostport(void)
201{
202 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
203 u32 i;
204
205 for (i = 0; i < 32; i++)
206 writel(hpcr_value[i], &dram->hpcr[i]);
207}
208
209static void mctl_setup_dram_clock(u32 clk)
210{
211 u32 reg_val;
212 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
213
214 /* setup DRAM PLL */
215 reg_val = readl(&ccm->pll5_cfg);
216 reg_val &= ~CCM_PLL5_CTRL_M_MASK; /* set M to 0 (x1) */
217 reg_val &= ~CCM_PLL5_CTRL_K_MASK; /* set K to 0 (x1) */
218 reg_val &= ~CCM_PLL5_CTRL_N_MASK; /* set N to 0 (x0) */
219 reg_val &= ~CCM_PLL5_CTRL_P_MASK; /* set P to 0 (x1) */
220 if (clk >= 540 && clk < 552) {
221 /* dram = 540MHz, pll5p = 540MHz */
222 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
223 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
224 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(15));
225 reg_val |= CCM_PLL5_CTRL_P(1);
226 } else if (clk >= 512 && clk < 528) {
227 /* dram = 512MHz, pll5p = 384MHz */
228 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
229 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(4));
230 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(16));
231 reg_val |= CCM_PLL5_CTRL_P(2);
232 } else if (clk >= 496 && clk < 504) {
233 /* dram = 496MHz, pll5p = 372MHz */
234 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
235 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
236 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(31));
237 reg_val |= CCM_PLL5_CTRL_P(2);
238 } else if (clk >= 468 && clk < 480) {
239 /* dram = 468MHz, pll5p = 468MHz */
240 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
241 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
242 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(13));
243 reg_val |= CCM_PLL5_CTRL_P(1);
244 } else if (clk >= 396 && clk < 408) {
245 /* dram = 396MHz, pll5p = 396MHz */
246 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
247 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
248 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(11));
249 reg_val |= CCM_PLL5_CTRL_P(1);
250 } else {
251 /* any other frequency that is a multiple of 24 */
252 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
253 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
254 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(clk / 24));
255 reg_val |= CCM_PLL5_CTRL_P(CCM_PLL5_CTRL_P_X(2));
256 }
257 reg_val &= ~CCM_PLL5_CTRL_VCO_GAIN; /* PLL VCO Gain off */
258 reg_val |= CCM_PLL5_CTRL_EN; /* PLL On */
259 writel(reg_val, &ccm->pll5_cfg);
260 udelay(5500);
261
262 setbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_DDR_CLK);
263
264#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I)
265 /* reset GPS */
266 clrbits_le32(&ccm->gps_clk_cfg, CCM_GPS_CTRL_RESET | CCM_GPS_CTRL_GATE);
267 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
268 udelay(1);
269 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
270#endif
271
Hans de Goede745325a2014-06-09 11:36:57 +0200272#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell286c3c32014-05-05 11:52:25 +0100273 /* setup MBUS clock */
274 reg_val = CCM_MBUS_CTRL_GATE |
Hans de Goedef84269c2014-06-09 11:36:58 +0200275#ifdef CONFIG_SUN7I
Ian Campbell286c3c32014-05-05 11:52:25 +0100276 CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
277 CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) |
278 CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
Hans de Goedef84269c2014-06-09 11:36:58 +0200279#else /* defined(CONFIG_SUN5I) */
280 CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) |
281 CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
282 CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
283#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100284 writel(reg_val, &ccm->mbus_clk_cfg);
Hans de Goede745325a2014-06-09 11:36:57 +0200285#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100286
287 /*
288 * open DRAMC AHB & DLL register clock
289 * close it first
290 */
Hans de Goede745325a2014-06-09 11:36:57 +0200291#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell286c3c32014-05-05 11:52:25 +0100292 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
Hans de Goede745325a2014-06-09 11:36:57 +0200293#else
294 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
295#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100296 udelay(22);
297
298 /* then open it */
Hans de Goede745325a2014-06-09 11:36:57 +0200299#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell286c3c32014-05-05 11:52:25 +0100300 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
Hans de Goede745325a2014-06-09 11:36:57 +0200301#else
302 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
303#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100304 udelay(22);
305}
306
307static int dramc_scan_readpipe(void)
308{
309 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
310 u32 reg_val;
311
312 /* data training trigger */
313#ifdef CONFIG_SUN7I
314 clrbits_le32(&dram->csr, DRAM_CSR_FAILED);
315#endif
316 setbits_le32(&dram->ccr, DRAM_CCR_DATA_TRAINING);
317
318 /* check whether data training process has completed */
319 await_completion(&dram->ccr, DRAM_CCR_DATA_TRAINING);
320
321 /* check data training result */
322 reg_val = readl(&dram->csr);
323 if (reg_val & DRAM_CSR_FAILED)
324 return -1;
325
326 return 0;
327}
328
Ian Campbell286c3c32014-05-05 11:52:25 +0100329static void dramc_clock_output_en(u32 on)
330{
331#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
332 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
333
334 if (on)
335 setbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
336 else
337 clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
338#endif
Hans de Goede745325a2014-06-09 11:36:57 +0200339#ifdef CONFIG_SUN4I
340 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
341 if (on)
342 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
343 else
344 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
345#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100346}
347
348static const u16 tRFC_table[2][6] = {
349 /* 256Mb 512Mb 1Gb 2Gb 4Gb 8Gb */
350 /* DDR2 75ns 105ns 127.5ns 195ns 327.5ns invalid */
351 { 77, 108, 131, 200, 336, 336 },
352 /* DDR3 invalid 90ns 110ns 160ns 300ns 350ns */
353 { 93, 93, 113, 164, 308, 359 }
354};
355
356static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
357{
358 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
359 u32 tRFC, tREFI;
360
361 tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
362 tREFI = (7987 * clk) >> 10; /* <= 7.8us */
363
364 writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr);
365}
366
Siarhei Siamashkaf2577962014-08-03 05:32:40 +0300367/*
368 * If the dram->ppwrsctl (SDR_DPCR) register has the lowest bit set to 1, this
369 * means that DRAM is currently in self-refresh mode and retaining the old
370 * data. Since we have no idea what to do in this situation yet, just set this
371 * register to 0 and initialize DRAM in the same way as on any normal reboot
372 * (discarding whatever was stored there).
373 *
374 * Note: on sun7i hardware, the highest 16 bits need to be set to 0x1651 magic
375 * value for this write operation to have any effect. On sun5i hadware this
376 * magic value is not necessary. And on sun4i hardware the writes to this
377 * register seem to have no effect at all.
378 */
379static void mctl_disable_power_save(void)
380{
381 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
382 writel(0x16510000, &dram->ppwrsctl);
383}
384
Ian Campbell286c3c32014-05-05 11:52:25 +0100385unsigned long dramc_init(struct dram_para *para)
386{
387 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
388 u32 reg_val;
389 u32 density;
390 int ret_val;
391
392 /* check input dram parameter structure */
393 if (!para)
394 return 0;
395
396 /* setup DRAM relative clock */
397 mctl_setup_dram_clock(para->clock);
398
Hans de Goedef84269c2014-06-09 11:36:58 +0200399 /* Disable any pad power save control */
Siarhei Siamashkaf2577962014-08-03 05:32:40 +0300400 mctl_disable_power_save();
Hans de Goedef84269c2014-06-09 11:36:58 +0200401
Ian Campbell286c3c32014-05-05 11:52:25 +0100402 /* reset external DRAM */
Hans de Goede745325a2014-06-09 11:36:57 +0200403#ifndef CONFIG_SUN7I
404 mctl_ddr3_reset();
405#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100406 mctl_set_drive();
407
408 /* dram clock off */
409 dramc_clock_output_en(0);
410
Hans de Goede745325a2014-06-09 11:36:57 +0200411#ifdef CONFIG_SUN4I
412 /* select dram controller 1 */
413 writel(DRAM_CSEL_MAGIC, &dram->csel);
414#endif
415
Ian Campbell286c3c32014-05-05 11:52:25 +0100416 mctl_itm_disable();
417 mctl_enable_dll0(para->tpr3);
418
419 /* configure external DRAM */
420 reg_val = 0x0;
421 if (para->type == DRAM_MEMORY_TYPE_DDR3)
422 reg_val |= DRAM_DCR_TYPE_DDR3;
423 reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);
424
425 if (para->density == 256)
426 density = DRAM_DCR_CHIP_DENSITY_256M;
427 else if (para->density == 512)
428 density = DRAM_DCR_CHIP_DENSITY_512M;
429 else if (para->density == 1024)
430 density = DRAM_DCR_CHIP_DENSITY_1024M;
431 else if (para->density == 2048)
432 density = DRAM_DCR_CHIP_DENSITY_2048M;
433 else if (para->density == 4096)
434 density = DRAM_DCR_CHIP_DENSITY_4096M;
435 else if (para->density == 8192)
436 density = DRAM_DCR_CHIP_DENSITY_8192M;
437 else
438 density = DRAM_DCR_CHIP_DENSITY_256M;
439
440 reg_val |= DRAM_DCR_CHIP_DENSITY(density);
441 reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
442 reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
443 reg_val |= DRAM_DCR_CMD_RANK_ALL;
444 reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE);
445 writel(reg_val, &dram->dcr);
446
447#ifdef CONFIG_SUN7I
448 setbits_le32(&dram->zqcr1, (0x1 << 24) | (0x1 << 1));
449 if (para->tpr4 & 0x2)
450 clrsetbits_le32(&dram->zqcr1, (0x1 << 24), (0x1 << 1));
451 dramc_clock_output_en(1);
452#endif
453
454#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
455 /* set odt impendance divide ratio */
456 reg_val = ((para->zq) >> 8) & 0xfffff;
457 reg_val |= ((para->zq) & 0xff) << 20;
458 reg_val |= (para->zq) & 0xf0000000;
459 writel(reg_val, &dram->zqcr0);
460#endif
461
462#ifdef CONFIG_SUN7I
463 /* Set CKE Delay to about 1ms */
464 setbits_le32(&dram->idcr, 0x1ffff);
465#endif
466
467#ifdef CONFIG_SUN7I
Siarhei Siamashkaf2577962014-08-03 05:32:40 +0300468 mctl_ddr3_reset();
Hans de Goede745325a2014-06-09 11:36:57 +0200469#else
470 /* dram clock on */
471 dramc_clock_output_en(1);
Ian Campbell286c3c32014-05-05 11:52:25 +0100472#endif
473
474 udelay(1);
475
476 await_completion(&dram->ccr, DRAM_CCR_INIT);
477
478 mctl_enable_dllx(para->tpr3);
479
Hans de Goede745325a2014-06-09 11:36:57 +0200480#ifdef CONFIG_SUN4I
481 /* set odt impedance divide ratio */
482 reg_val = ((para->zq) >> 8) & 0xfffff;
483 reg_val |= ((para->zq) & 0xff) << 20;
484 reg_val |= (para->zq) & 0xf0000000;
485 writel(reg_val, &dram->zqcr0);
486#endif
487
488#ifdef CONFIG_SUN4I
489 /* set I/O configure register */
490 reg_val = 0x00cc0000;
491 reg_val |= (para->odt_en) & 0x3;
492 reg_val |= ((para->odt_en) & 0x3) << 30;
493 writel(reg_val, &dram->iocr);
494#endif
495
Ian Campbell286c3c32014-05-05 11:52:25 +0100496 /* set refresh period */
497 dramc_set_autorefresh_cycle(para->clock, para->type - 2, density);
498
499 /* set timing parameters */
500 writel(para->tpr0, &dram->tpr0);
501 writel(para->tpr1, &dram->tpr1);
502 writel(para->tpr2, &dram->tpr2);
503
504 if (para->type == DRAM_MEMORY_TYPE_DDR3) {
505 reg_val = DRAM_MR_BURST_LENGTH(0x0);
506#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
507 reg_val |= DRAM_MR_POWER_DOWN;
508#endif
509 reg_val |= DRAM_MR_CAS_LAT(para->cas - 4);
510 reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
511 } else if (para->type == DRAM_MEMORY_TYPE_DDR2) {
512 reg_val = DRAM_MR_BURST_LENGTH(0x2);
513 reg_val |= DRAM_MR_CAS_LAT(para->cas);
514 reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
515 }
516 writel(reg_val, &dram->mr);
517
518 writel(para->emr1, &dram->emr);
519 writel(para->emr2, &dram->emr2);
520 writel(para->emr3, &dram->emr3);
521
522 /* set DQS window mode */
523 clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE);
524
525#ifdef CONFIG_SUN7I
526 /* Command rate timing mode 2T & 1T */
527 if (para->tpr4 & 0x1)
528 setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T);
529#endif
530 /* reset external DRAM */
531 setbits_le32(&dram->ccr, DRAM_CCR_INIT);
532 await_completion(&dram->ccr, DRAM_CCR_INIT);
533
Ian Campbell286c3c32014-05-05 11:52:25 +0100534 /* scan read pipe value */
535 mctl_itm_enable();
Siarhei Siamashka34759d72014-08-03 05:32:39 +0300536 ret_val = dramc_scan_readpipe();
Ian Campbell286c3c32014-05-05 11:52:25 +0100537
538 if (ret_val < 0)
539 return 0;
540
541 /* configure all host port */
542 mctl_configure_hostport();
543
544 return get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
545}