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