1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <common.h>
24#include <init.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#include <linux/delay.h>
31
32#define CPU_CFG_CHIP_VER(n) ((n) << 6)
33#define CPU_CFG_CHIP_VER_MASK CPU_CFG_CHIP_VER(0x3)
34#define CPU_CFG_CHIP_REV_A 0x0
35#define CPU_CFG_CHIP_REV_C1 0x1
36#define CPU_CFG_CHIP_REV_C2 0x2
37#define CPU_CFG_CHIP_REV_B 0x3
38
39
40
41
42static inline void await_bits_clear(u32 *reg, u32 mask)
43{
44 mctl_await_completion(reg, mask, 0);
45}
46
47
48
49
50static inline void await_bits_set(u32 *reg, u32 mask)
51{
52 mctl_await_completion(reg, mask, mask);
53}
54
55
56
57
58
59
60static void mctl_ddr3_reset(void)
61{
62 struct sunxi_dram_reg *dram =
63 (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
64
65#ifdef CONFIG_MACH_SUN4I
66 struct sunxi_timer_reg *timer =
67 (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
68 u32 reg_val;
69
70 writel(0, &timer->cpu_cfg);
71 reg_val = readl(&timer->cpu_cfg);
72
73 if ((reg_val & CPU_CFG_CHIP_VER_MASK) !=
74 CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) {
75 setbits_le32(&dram->mcr, DRAM_MCR_RESET);
76 udelay(200);
77 clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
78 } else
79#endif
80 {
81 clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
82 udelay(200);
83 setbits_le32(&dram->mcr, DRAM_MCR_RESET);
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97 udelay(500);
98}
99
100static void mctl_set_drive(void)
101{
102 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
103
104#ifdef CONFIG_MACH_SUN7I
105 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
106#else
107 clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3),
108#endif
109 DRAM_MCR_MODE_EN(0x3) |
110 0xffc);
111}
112
113static void mctl_itm_disable(void)
114{
115 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
116
117 clrsetbits_le32(&dram->ccr, DRAM_CCR_INIT, DRAM_CCR_ITM_OFF);
118}
119
120static void mctl_itm_enable(void)
121{
122 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
123
124 clrbits_le32(&dram->ccr, DRAM_CCR_ITM_OFF);
125}
126
127static void mctl_itm_reset(void)
128{
129 mctl_itm_disable();
130 udelay(1);
131 mctl_itm_enable();
132 udelay(1);
133}
134
135static void mctl_enable_dll0(u32 phase)
136{
137 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
138
139 clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
140 ((phase >> 16) & 0x3f) << 6);
141 clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE);
142 udelay(2);
143
144 clrbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET | DRAM_DLLCR_DISABLE);
145 udelay(22);
146
147 clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_DISABLE, DRAM_DLLCR_NRESET);
148 udelay(22);
149}
150
151
152static u32 mctl_get_number_of_lanes(void)
153{
154 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
155 if ((readl(&dram->dcr) & DRAM_DCR_BUS_WIDTH_MASK) ==
156 DRAM_DCR_BUS_WIDTH(DRAM_DCR_BUS_WIDTH_32BIT))
157 return 4;
158 else
159 return 2;
160}
161
162
163
164
165static void mctl_enable_dllx(u32 phase)
166{
167 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
168 u32 i, number_of_lanes;
169
170 number_of_lanes = mctl_get_number_of_lanes();
171
172 for (i = 1; i <= number_of_lanes; i++) {
173 clrsetbits_le32(&dram->dllcr[i], 0xf << 14,
174 (phase & 0xf) << 14);
175 clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET,
176 DRAM_DLLCR_DISABLE);
177 phase >>= 4;
178 }
179 udelay(2);
180
181 for (i = 1; i <= number_of_lanes; i++)
182 clrbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET |
183 DRAM_DLLCR_DISABLE);
184 udelay(22);
185
186 for (i = 1; i <= number_of_lanes; i++)
187 clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_DISABLE,
188 DRAM_DLLCR_NRESET);
189 udelay(22);
190}
191
192static u32 hpcr_value[32] = {
193#ifdef CONFIG_MACH_SUN5I
194 0, 0, 0, 0,
195 0, 0, 0, 0,
196 0, 0, 0, 0,
197 0, 0, 0, 0,
198 0x1031, 0x1031, 0x0735, 0x1035,
199 0x1035, 0x0731, 0x1031, 0,
200 0x0301, 0x0301, 0x0301, 0x0301,
201 0x0301, 0x0301, 0x0301, 0
202#endif
203#ifdef CONFIG_MACH_SUN4I
204 0x0301, 0x0301, 0x0301, 0x0301,
205 0x0301, 0x0301, 0, 0,
206 0, 0, 0, 0,
207 0, 0, 0, 0,
208 0x1031, 0x1031, 0x0735, 0x5031,
209 0x1035, 0x0731, 0x1031, 0x0735,
210 0x1035, 0x1031, 0x0731, 0x1035,
211 0x1031, 0x0301, 0x0301, 0x0731
212#endif
213#ifdef CONFIG_MACH_SUN7I
214 0x0301, 0x0301, 0x0301, 0x0301,
215 0x0301, 0x0301, 0x0301, 0x0301,
216 0, 0, 0, 0,
217 0, 0, 0, 0,
218 0x1031, 0x1031, 0x0735, 0x1035,
219 0x1035, 0x0731, 0x1031, 0x0735,
220 0x1035, 0x1031, 0x0731, 0x1035,
221 0x0001, 0x1031, 0, 0x1031
222
223
224
225
226
227#endif
228};
229
230static void mctl_configure_hostport(void)
231{
232 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
233 u32 i;
234
235 for (i = 0; i < 32; i++)
236 writel(hpcr_value[i], &dram->hpcr[i]);
237}
238
239static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk)
240{
241 u32 reg_val;
242 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
243 u32 pll5p_clk, pll6x_clk;
244 u32 pll5p_div, pll6x_div;
245 u32 pll5p_rate, pll6x_rate;
246
247
248 reg_val = readl(&ccm->pll5_cfg);
249 reg_val &= ~CCM_PLL5_CTRL_M_MASK;
250 reg_val &= ~CCM_PLL5_CTRL_K_MASK;
251 reg_val &= ~CCM_PLL5_CTRL_N_MASK;
252 reg_val &= ~CCM_PLL5_CTRL_P_MASK;
253#ifdef CONFIG_OLD_SUNXI_KERNEL_COMPAT
254
255 reg_val |= CCM_PLL5_CTRL_P(1);
256#endif
257 if (clk >= 540 && clk < 552) {
258
259 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
260 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
261 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(15));
262 } else if (clk >= 512 && clk < 528) {
263
264 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
265 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(4));
266 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(16));
267 } else if (clk >= 496 && clk < 504) {
268
269 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
270 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
271 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(31));
272 } else if (clk >= 468 && clk < 480) {
273
274 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
275 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
276 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(13));
277 } else if (clk >= 396 && clk < 408) {
278
279 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
280 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
281 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(11));
282 } else {
283
284 reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
285 reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
286 reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(clk / 24));
287 }
288 reg_val &= ~CCM_PLL5_CTRL_VCO_GAIN;
289 reg_val |= CCM_PLL5_CTRL_EN;
290 writel(reg_val, &ccm->pll5_cfg);
291 udelay(5500);
292
293 setbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_DDR_CLK);
294
295#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
296
297 clrbits_le32(&ccm->gps_clk_cfg, CCM_GPS_CTRL_RESET | CCM_GPS_CTRL_GATE);
298 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
299 udelay(1);
300 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
301#endif
302
303
304 if (!mbus_clk)
305 mbus_clk = 300;
306
307
308 pll6x_clk = clock_get_pll6() / 1000000;
309#ifdef CONFIG_MACH_SUN7I
310 pll6x_clk *= 2;
311#endif
312 pll5p_clk = clock_get_pll5p() / 1000000;
313 pll6x_div = DIV_ROUND_UP(pll6x_clk, mbus_clk);
314 pll5p_div = DIV_ROUND_UP(pll5p_clk, mbus_clk);
315 pll6x_rate = pll6x_clk / pll6x_div;
316 pll5p_rate = pll5p_clk / pll5p_div;
317
318 if (pll6x_div <= 16 && pll6x_rate > pll5p_rate) {
319
320 reg_val = CCM_MBUS_CTRL_GATE |
321 CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
322 CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
323 CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(pll6x_div));
324 } else if (pll5p_div <= 16) {
325
326 reg_val = CCM_MBUS_CTRL_GATE |
327 CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) |
328 CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
329 CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(pll5p_div));
330 } else {
331 panic("Bad mbus_clk\n");
332 }
333 writel(reg_val, &ccm->mbus_clk_cfg);
334
335
336
337
338
339#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
340 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
341#else
342 clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
343#endif
344 udelay(22);
345
346
347#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
348 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
349#else
350 setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
351#endif
352 udelay(22);
353}
354
355
356
357
358
359
360
361
362
363
364
365
366
367static void mctl_set_dqs_gating_delay(int rank, u32 dqs_gating_delay)
368{
369 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
370 u32 lane, number_of_lanes = mctl_get_number_of_lanes();
371
372 u32 slr = readl(rank == 0 ? &dram->rslr0 : &dram->rslr1);
373
374 u32 dgr = readl(rank == 0 ? &dram->rdgr0 : &dram->rdgr1);
375 for (lane = 0; lane < number_of_lanes; lane++) {
376 u32 tmp = dqs_gating_delay >> (lane * 8);
377 slr &= ~(7 << (lane * 3));
378 slr |= ((tmp >> 2) & 7) << (lane * 3);
379 dgr &= ~(3 << (lane * 2));
380 dgr |= (tmp & 3) << (lane * 2);
381 }
382 writel(slr, rank == 0 ? &dram->rslr0 : &dram->rslr1);
383 writel(dgr, rank == 0 ? &dram->rdgr0 : &dram->rdgr1);
384}
385
386static int dramc_scan_readpipe(void)
387{
388 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
389 u32 reg_val;
390
391
392 clrbits_le32(&dram->csr, DRAM_CSR_FAILED);
393 setbits_le32(&dram->ccr, DRAM_CCR_DATA_TRAINING);
394
395
396 await_bits_clear(&dram->ccr, DRAM_CCR_DATA_TRAINING);
397
398
399 reg_val = readl(&dram->csr);
400 if (reg_val & DRAM_CSR_FAILED)
401 return -1;
402
403 return 0;
404}
405
406static void dramc_clock_output_en(u32 on)
407{
408#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
409 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
410
411 if (on)
412 setbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
413 else
414 clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
415#endif
416#ifdef CONFIG_MACH_SUN4I
417 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
418 if (on)
419 setbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT);
420 else
421 clrbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT);
422#endif
423}
424
425
426static const u16 tRFC_DDR3_table[6] = {
427
428 90, 90, 110, 160, 300, 350
429};
430
431static void dramc_set_autorefresh_cycle(u32 clk, u32 density)
432{
433 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
434 u32 tRFC, tREFI;
435
436 tRFC = (tRFC_DDR3_table[density] * clk + 999) / 1000;
437 tREFI = (7987 * clk) >> 10;
438
439 writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr);
440}
441
442
443static u32 ddr3_write_recovery(u32 clk)
444{
445 u32 twr_ns = 15;
446 u32 twr_ck = (twr_ns * clk + 999) / 1000;
447 if (twr_ck < 5)
448 return 1;
449 else if (twr_ck <= 8)
450 return twr_ck - 4;
451 else if (twr_ck <= 10)
452 return 5;
453 else
454 return 6;
455}
456
457
458
459
460
461
462
463
464
465
466
467
468
469static void mctl_disable_power_save(void)
470{
471 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
472 writel(0x16510000, &dram->ppwrsctl);
473}
474
475
476
477
478
479
480
481
482static void mctl_set_cke_delay(void)
483{
484 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
485
486
487
488
489
490
491
492 setbits_le32(&dram->idcr, 0x1ffff);
493}
494
495
496
497
498
499
500
501
502static void mctl_ddr3_initialize(void)
503{
504 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
505 setbits_le32(&dram->ccr, DRAM_CCR_INIT);
506 await_bits_clear(&dram->ccr, DRAM_CCR_INIT);
507}
508
509
510
511
512static void mctl_set_impedance(u32 zq, bool odt_en)
513{
514 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
515 u32 reg_val;
516 u32 zprog = zq & 0xFF, zdata = (zq >> 8) & 0xFFFFF;
517
518#ifndef CONFIG_MACH_SUN7I
519
520
521
522
523 await_bits_set(&dram->zqsr, DRAM_ZQSR_ZDONE);
524#endif
525
526
527 if (!odt_en)
528 return;
529
530#ifdef CONFIG_MACH_SUN7I
531
532
533
534
535
536
537 writel((1 << 24) | (1 << 1), &dram->zqcr1);
538#endif
539
540
541 clrbits_le32(&dram->zqcr0, DRAM_ZQCR0_ZCAL);
542
543 if (zdata) {
544
545 reg_val = DRAM_ZQCR0_ZDEN | zdata;
546 writel(reg_val, &dram->zqcr0);
547
548 } else {
549
550 reg_val = DRAM_ZQCR0_ZCAL | DRAM_ZQCR0_IMP_DIV(zprog);
551 writel(reg_val, &dram->zqcr0);
552
553 await_bits_set(&dram->zqsr, DRAM_ZQSR_ZDONE);
554 }
555
556
557 clrbits_le32(&dram->zqcr0, DRAM_ZQCR0_ZCAL);
558
559
560 writel(DRAM_IOCR_ODT_EN, &dram->iocr);
561}
562
563static unsigned long dramc_init_helper(struct dram_para *para)
564{
565 struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
566 u32 reg_val;
567 u32 density;
568 int ret_val;
569
570
571
572
573
574 if (para->type != DRAM_MEMORY_TYPE_DDR3 || para->rank_num != 1)
575 return 0;
576
577
578 mctl_setup_dram_clock(para->clock, para->mbus_clock);
579
580
581 mctl_disable_power_save();
582
583 mctl_set_drive();
584
585
586 dramc_clock_output_en(0);
587
588#ifdef CONFIG_MACH_SUN4I
589
590 writel(DRAM_CSEL_MAGIC, &dram->csel);
591#endif
592
593 mctl_itm_disable();
594 mctl_enable_dll0(para->tpr3);
595
596
597 reg_val = DRAM_DCR_TYPE_DDR3;
598 reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);
599
600 if (para->density == 256)
601 density = DRAM_DCR_CHIP_DENSITY_256M;
602 else if (para->density == 512)
603 density = DRAM_DCR_CHIP_DENSITY_512M;
604 else if (para->density == 1024)
605 density = DRAM_DCR_CHIP_DENSITY_1024M;
606 else if (para->density == 2048)
607 density = DRAM_DCR_CHIP_DENSITY_2048M;
608 else if (para->density == 4096)
609 density = DRAM_DCR_CHIP_DENSITY_4096M;
610 else if (para->density == 8192)
611 density = DRAM_DCR_CHIP_DENSITY_8192M;
612 else
613 density = DRAM_DCR_CHIP_DENSITY_256M;
614
615 reg_val |= DRAM_DCR_CHIP_DENSITY(density);
616 reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
617 reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
618 reg_val |= DRAM_DCR_CMD_RANK_ALL;
619 reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE);
620 writel(reg_val, &dram->dcr);
621
622 dramc_clock_output_en(1);
623
624 mctl_set_impedance(para->zq, para->odt_en);
625
626 mctl_set_cke_delay();
627
628 mctl_ddr3_reset();
629
630 udelay(1);
631
632 await_bits_clear(&dram->ccr, DRAM_CCR_INIT);
633
634 mctl_enable_dllx(para->tpr3);
635
636
637 dramc_set_autorefresh_cycle(para->clock, density);
638
639
640 writel(para->tpr0, &dram->tpr0);
641 writel(para->tpr1, &dram->tpr1);
642 writel(para->tpr2, &dram->tpr2);
643
644 reg_val = DRAM_MR_BURST_LENGTH(0x0);
645#if (defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I))
646 reg_val |= DRAM_MR_POWER_DOWN;
647#endif
648 reg_val |= DRAM_MR_CAS_LAT(para->cas - 4);
649 reg_val |= DRAM_MR_WRITE_RECOVERY(ddr3_write_recovery(para->clock));
650 writel(reg_val, &dram->mr);
651
652 writel(para->emr1, &dram->emr);
653 writel(para->emr2, &dram->emr2);
654 writel(para->emr3, &dram->emr3);
655
656
657 clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE);
658
659#ifdef CONFIG_MACH_SUN7I
660
661 if (para->tpr4 & 0x1)
662 setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T);
663#endif
664
665 mctl_ddr3_initialize();
666
667
668 mctl_itm_enable();
669
670
671 ret_val = dramc_scan_readpipe();
672
673 if (ret_val < 0)
674 return 0;
675
676
677 if (para->dqs_gating_delay)
678 mctl_set_dqs_gating_delay(0, para->dqs_gating_delay);
679
680
681 if (para->active_windowing)
682 clrbits_le32(&dram->ccr, DRAM_CCR_DQS_GATE);
683 else
684 setbits_le32(&dram->ccr, DRAM_CCR_DQS_GATE);
685
686 mctl_itm_reset();
687
688
689 mctl_configure_hostport();
690
691 return get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
692}
693
694unsigned long dramc_init(struct dram_para *para)
695{
696 unsigned long dram_size, actual_density;
697
698
699 if (!para)
700 return 0;
701
702
703 if (para->io_width && para->bus_width && para->density)
704 return dramc_init_helper(para);
705
706
707 para->io_width = 16;
708 para->bus_width = 32;
709#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I)
710
711 para->density = 4096;
712#else
713
714 para->density = 8192;
715#endif
716
717 dram_size = dramc_init_helper(para);
718 if (!dram_size) {
719
720 para->bus_width = 16;
721 dram_size = dramc_init_helper(para);
722 if (!dram_size) {
723
724 return dram_size;
725 }
726 }
727
728
729 actual_density = (dram_size >> 17) * para->io_width / para->bus_width;
730
731 if (actual_density != para->density) {
732
733 para->density = actual_density;
734 dram_size = dramc_init_helper(para);
735 }
736
737 return dram_size;
738}
739