blob: 236eed7711194f40240c160d89651087d33bcaf6 [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
51static void mctl_ddr3_reset(void)
52{
53 struct sunxi_dram_reg *dram =
54 (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
55
Hans de Goede745325a2014-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 Campbell286c3c32014-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 Goede745325a2014-06-09 11:36:57 +020082#ifdef CONFIG_SUN7I
Ian Campbell286c3c32014-05-05 11:52:25 +010083 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
Hans de Goede745325a2014-06-09 11:36:57 +020084#else
85 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3),
86#endif
Ian Campbell286c3c32014-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 Goedef84269c2014-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 Goede745325a2014-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 Campbell286c3c32014-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 Goede745325a2014-06-09 11:36:57 +0200267#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell286c3c32014-05-05 11:52:25 +0100268 /* setup MBUS clock */
269 reg_val = CCM_MBUS_CTRL_GATE |
Hans de Goedef84269c2014-06-09 11:36:58 +0200270#ifdef CONFIG_SUN7I
Ian Campbell286c3c32014-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 Goedef84269c2014-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 Campbell286c3c32014-05-05 11:52:25 +0100279 writel(reg_val, &ccm->mbus_clk_cfg);
Hans de Goede745325a2014-06-09 11:36:57 +0200280#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100281
282 /*
283 * open DRAMC AHB & DLL register clock
284 * close it first
285 */
Hans de Goede745325a2014-06-09 11:36:57 +0200286#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell286c3c32014-05-05 11:52:25 +0100287 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
Hans de Goede745325a2014-06-09 11:36:57 +0200288#else
289 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
290#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100291 udelay(22);
292
293 /* then open it */
Hans de Goede745325a2014-06-09 11:36:57 +0200294#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
Ian Campbell286c3c32014-05-05 11:52:25 +0100295 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
Hans de Goede745325a2014-06-09 11:36:57 +0200296#else
297 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
298#endif
Ian Campbell286c3c32014-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 Campbell286c3c32014-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 Goede745325a2014-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 Campbell286c3c32014-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
362unsigned long dramc_init(struct dram_para *para)
363{
364 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
365 u32 reg_val;
366 u32 density;
367 int ret_val;
368
369 /* check input dram parameter structure */
370 if (!para)
371 return 0;
372
373 /* setup DRAM relative clock */
374 mctl_setup_dram_clock(para->clock);
375
Hans de Goedef84269c2014-06-09 11:36:58 +0200376#ifdef CONFIG_SUN5I
377 /* Disable any pad power save control */
378 writel(0, &dram->ppwrsctl);
379#endif
380
Ian Campbell286c3c32014-05-05 11:52:25 +0100381 /* reset external DRAM */
Hans de Goede745325a2014-06-09 11:36:57 +0200382#ifndef CONFIG_SUN7I
383 mctl_ddr3_reset();
384#endif
Ian Campbell286c3c32014-05-05 11:52:25 +0100385 mctl_set_drive();
386
387 /* dram clock off */
388 dramc_clock_output_en(0);
389
Hans de Goede745325a2014-06-09 11:36:57 +0200390#ifdef CONFIG_SUN4I
391 /* select dram controller 1 */
392 writel(DRAM_CSEL_MAGIC, &dram->csel);
393#endif
394
Ian Campbell286c3c32014-05-05 11:52:25 +0100395 mctl_itm_disable();
396 mctl_enable_dll0(para->tpr3);
397
398 /* configure external DRAM */
399 reg_val = 0x0;
400 if (para->type == DRAM_MEMORY_TYPE_DDR3)
401 reg_val |= DRAM_DCR_TYPE_DDR3;
402 reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);
403
404 if (para->density == 256)
405 density = DRAM_DCR_CHIP_DENSITY_256M;
406 else if (para->density == 512)
407 density = DRAM_DCR_CHIP_DENSITY_512M;
408 else if (para->density == 1024)
409 density = DRAM_DCR_CHIP_DENSITY_1024M;
410 else if (para->density == 2048)
411 density = DRAM_DCR_CHIP_DENSITY_2048M;
412 else if (para->density == 4096)
413 density = DRAM_DCR_CHIP_DENSITY_4096M;
414 else if (para->density == 8192)
415 density = DRAM_DCR_CHIP_DENSITY_8192M;
416 else
417 density = DRAM_DCR_CHIP_DENSITY_256M;
418
419 reg_val |= DRAM_DCR_CHIP_DENSITY(density);
420 reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
421 reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
422 reg_val |= DRAM_DCR_CMD_RANK_ALL;
423 reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE);
424 writel(reg_val, &dram->dcr);
425
426#ifdef CONFIG_SUN7I
427 setbits_le32(&dram->zqcr1, (0x1 << 24) | (0x1 << 1));
428 if (para->tpr4 & 0x2)
429 clrsetbits_le32(&dram->zqcr1, (0x1 << 24), (0x1 << 1));
430 dramc_clock_output_en(1);
431#endif
432
433#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
434 /* set odt impendance divide ratio */
435 reg_val = ((para->zq) >> 8) & 0xfffff;
436 reg_val |= ((para->zq) & 0xff) << 20;
437 reg_val |= (para->zq) & 0xf0000000;
438 writel(reg_val, &dram->zqcr0);
439#endif
440
441#ifdef CONFIG_SUN7I
442 /* Set CKE Delay to about 1ms */
443 setbits_le32(&dram->idcr, 0x1ffff);
444#endif
445
446#ifdef CONFIG_SUN7I
447 if ((readl(&dram->ppwrsctl) & 0x1) != 0x1)
448 mctl_ddr3_reset();
449 else
450 setbits_le32(&dram->mcr, DRAM_MCR_RESET);
Hans de Goede745325a2014-06-09 11:36:57 +0200451#else
452 /* dram clock on */
453 dramc_clock_output_en(1);
Ian Campbell286c3c32014-05-05 11:52:25 +0100454#endif
455
456 udelay(1);
457
458 await_completion(&dram->ccr, DRAM_CCR_INIT);
459
460 mctl_enable_dllx(para->tpr3);
461
Hans de Goede745325a2014-06-09 11:36:57 +0200462#ifdef CONFIG_SUN4I
463 /* set odt impedance divide ratio */
464 reg_val = ((para->zq) >> 8) & 0xfffff;
465 reg_val |= ((para->zq) & 0xff) << 20;
466 reg_val |= (para->zq) & 0xf0000000;
467 writel(reg_val, &dram->zqcr0);
468#endif
469
470#ifdef CONFIG_SUN4I
471 /* set I/O configure register */
472 reg_val = 0x00cc0000;
473 reg_val |= (para->odt_en) & 0x3;
474 reg_val |= ((para->odt_en) & 0x3) << 30;
475 writel(reg_val, &dram->iocr);
476#endif
477
Ian Campbell286c3c32014-05-05 11:52:25 +0100478 /* set refresh period */
479 dramc_set_autorefresh_cycle(para->clock, para->type - 2, density);
480
481 /* set timing parameters */
482 writel(para->tpr0, &dram->tpr0);
483 writel(para->tpr1, &dram->tpr1);
484 writel(para->tpr2, &dram->tpr2);
485
486 if (para->type == DRAM_MEMORY_TYPE_DDR3) {
487 reg_val = DRAM_MR_BURST_LENGTH(0x0);
488#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
489 reg_val |= DRAM_MR_POWER_DOWN;
490#endif
491 reg_val |= DRAM_MR_CAS_LAT(para->cas - 4);
492 reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
493 } else if (para->type == DRAM_MEMORY_TYPE_DDR2) {
494 reg_val = DRAM_MR_BURST_LENGTH(0x2);
495 reg_val |= DRAM_MR_CAS_LAT(para->cas);
496 reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
497 }
498 writel(reg_val, &dram->mr);
499
500 writel(para->emr1, &dram->emr);
501 writel(para->emr2, &dram->emr2);
502 writel(para->emr3, &dram->emr3);
503
504 /* set DQS window mode */
505 clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE);
506
507#ifdef CONFIG_SUN7I
508 /* Command rate timing mode 2T & 1T */
509 if (para->tpr4 & 0x1)
510 setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T);
511#endif
512 /* reset external DRAM */
513 setbits_le32(&dram->ccr, DRAM_CCR_INIT);
514 await_completion(&dram->ccr, DRAM_CCR_INIT);
515
516#ifdef CONFIG_SUN7I
517 /* setup zq calibration manual */
518 reg_val = readl(&dram->ppwrsctl);
519 if ((reg_val & 0x1) == 1) {
520 /* super_standby_flag = 1 */
521
522 reg_val = readl(0x01c20c00 + 0x120); /* rtc */
523 reg_val &= 0x000fffff;
524 reg_val |= 0x17b00000;
525 writel(reg_val, &dram->zqcr0);
526
527 /* exit self-refresh state */
528 clrsetbits_le32(&dram->dcr, 0x1f << 27, 0x12 << 27);
529 /* check whether command has been executed */
530 await_completion(&dram->dcr, 0x1 << 31);
531
532 udelay(2);
533
534 /* dram pad hold off */
535 setbits_le32(&dram->ppwrsctl, 0x16510000);
536
537 await_completion(&dram->ppwrsctl, 0x1);
538
539 /* exit self-refresh state */
540 clrsetbits_le32(&dram->dcr, 0x1f << 27, 0x12 << 27);
541
542 /* check whether command has been executed */
543 await_completion(&dram->dcr, 0x1 << 31);
544
545 udelay(2);
546
547 /* issue a refresh command */
548 clrsetbits_le32(&dram->dcr, 0x1f << 27, 0x13 << 27);
549 await_completion(&dram->dcr, 0x1 << 31);
550
551 udelay(2);
552 }
553#endif
554
555 /* scan read pipe value */
556 mctl_itm_enable();
Siarhei Siamashka34759d72014-08-03 05:32:39 +0300557 ret_val = dramc_scan_readpipe();
Ian Campbell286c3c32014-05-05 11:52:25 +0100558
559 if (ret_val < 0)
560 return 0;
561
562 /* configure all host port */
563 mctl_configure_hostport();
564
565 return get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
566}