sunxi: enable dual rank memory on R40
[platform/kernel/u-boot.git] / arch / arm / mach-sunxi / dram_sunxi_dw.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * sun8i H3 platform dram controller init
4  *
5  * (C) Copyright 2007-2015 Allwinner Technology Co.
6  *                         Jerry Wang <wangflord@allwinnertech.com>
7  * (C) Copyright 2015      Vishnu Patekar <vishnupatekar0510@gmail.com>
8  * (C) Copyright 2015      Hans de Goede <hdegoede@redhat.com>
9  * (C) Copyright 2015      Jens Kuske <jenskuske@gmail.com>
10  */
11 #include <common.h>
12 #include <init.h>
13 #include <log.h>
14 #include <asm/io.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/dram.h>
17 #include <asm/arch/cpu.h>
18 #include <linux/delay.h>
19 #include <linux/kconfig.h>
20
21 static void mctl_phy_init(u32 val)
22 {
23         struct sunxi_mctl_ctl_reg * const mctl_ctl =
24                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
25
26         writel(val | PIR_INIT, &mctl_ctl->pir);
27         mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1);
28 }
29
30 static void mctl_set_bit_delays(struct dram_para *para)
31 {
32         struct sunxi_mctl_ctl_reg * const mctl_ctl =
33                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
34         int i, j;
35
36         clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
37
38         for (i = 0; i < NR_OF_BYTE_LANES; i++)
39                 for (j = 0; j < LINES_PER_BYTE_LANE; j++)
40                         writel(DXBDLR_WRITE_DELAY(para->dx_write_delays[i][j]) |
41                                DXBDLR_READ_DELAY(para->dx_read_delays[i][j]),
42                                &mctl_ctl->dx[i].bdlr[j]);
43
44         for (i = 0; i < 31; i++)
45                 writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
46                        &mctl_ctl->acbdlr[i]);
47
48 #ifdef CONFIG_MACH_SUN8I_R40
49         /* DQSn, DMn, DQn output enable bit delay */
50         for (i = 0; i < 4; i++)
51                 writel(0x6 << 24, &mctl_ctl->dx[i].sdlr);
52 #endif
53
54         setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
55 }
56
57 enum {
58         MBUS_PORT_CPU           = 0,
59         MBUS_PORT_GPU           = 1,
60         MBUS_PORT_UNUSED        = 2,
61         MBUS_PORT_DMA           = 3,
62         MBUS_PORT_VE            = 4,
63         MBUS_PORT_CSI           = 5,
64         MBUS_PORT_NAND          = 6,
65         MBUS_PORT_SS            = 7,
66         MBUS_PORT_DE_V3S        = 8,
67         MBUS_PORT_DE_CFD_V3S    = 9,
68         MBUS_PORT_TS            = 8,
69         MBUS_PORT_DI            = 9,
70         MBUS_PORT_DE            = 10,
71         MBUS_PORT_DE_CFD        = 11,
72         MBUS_PORT_UNKNOWN1      = 12,
73         MBUS_PORT_UNKNOWN2      = 13,
74         MBUS_PORT_UNKNOWN3      = 14,
75 };
76
77 enum {
78         MBUS_QOS_LOWEST = 0,
79         MBUS_QOS_LOW,
80         MBUS_QOS_HIGH,
81         MBUS_QOS_HIGHEST
82 };
83
84 static inline void mbus_configure_port(u8 port,
85                                        bool bwlimit,
86                                        bool priority,
87                                        u8 qos,         /* MBUS_QOS_LOWEST .. MBUS_QOS_HIGEST */
88                                        u8 waittime,    /* 0 .. 0xf */
89                                        u8 acs,         /* 0 .. 0xff */
90                                        u16 bwl0,       /* 0 .. 0xffff, bandwidth limit in MB/s */
91                                        u16 bwl1,
92                                        u16 bwl2)
93 {
94         struct sunxi_mctl_com_reg * const mctl_com =
95                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
96
97         const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
98                            | (priority ? (1 << 1) : 0)
99                            | ((qos & 0x3) << 2)
100                            | ((waittime & 0xf) << 4)
101                            | ((acs & 0xff) << 8)
102                            | (bwl0 << 16) );
103         const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
104
105         debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
106         writel(cfg0, &mctl_com->mcr[port][0]);
107         writel(cfg1, &mctl_com->mcr[port][1]);
108 }
109
110 #define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2)    \
111         mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
112                             MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
113
114 static void mctl_set_master_priority_h3(void)
115 {
116         struct sunxi_mctl_com_reg * const mctl_com =
117                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
118
119         /* enable bandwidth limit windows and set windows size 1us */
120         writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
121
122         /* set cpu high priority */
123         writel(0x00000001, &mctl_com->mapr);
124
125         MBUS_CONF(   CPU,  true, HIGHEST, 0,  512,  256,  128);
126         MBUS_CONF(   GPU,  true,    HIGH, 0, 1536, 1024,  256);
127         MBUS_CONF(UNUSED,  true, HIGHEST, 0,  512,  256,   96);
128         MBUS_CONF(   DMA,  true, HIGHEST, 0,  256,  128,   32);
129         MBUS_CONF(    VE,  true,    HIGH, 0, 1792, 1600,  256);
130         MBUS_CONF(   CSI,  true, HIGHEST, 0,  256,  128,   32);
131         MBUS_CONF(  NAND,  true,    HIGH, 0,  256,  128,   64);
132         MBUS_CONF(    SS,  true, HIGHEST, 0,  256,  128,   64);
133         MBUS_CONF(    TS,  true, HIGHEST, 0,  256,  128,   64);
134         MBUS_CONF(    DI,  true,    HIGH, 0, 1024,  256,   64);
135         MBUS_CONF(    DE,  true, HIGHEST, 3, 8192, 6120, 1024);
136         MBUS_CONF(DE_CFD,  true,    HIGH, 0, 1024,  288,   64);
137 }
138
139 static void mctl_set_master_priority_v3s(void)
140 {
141         struct sunxi_mctl_com_reg * const mctl_com =
142                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
143
144         /* enable bandwidth limit windows and set windows size 1us */
145         writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
146
147         /* set cpu high priority */
148         writel(0x00000001, &mctl_com->mapr);
149
150         MBUS_CONF(       CPU,  true, HIGHEST, 0,  160,  100,   80);
151         MBUS_CONF(       GPU,  true,    HIGH, 0, 1792, 1536,    0);
152         MBUS_CONF(    UNUSED,  true, HIGHEST, 0,  256,  128,   80);
153         MBUS_CONF(       DMA,  true,    HIGH, 0,  256,  100,    0);
154         MBUS_CONF(        VE,  true,    HIGH, 0, 2048, 1600,    0);
155         MBUS_CONF(       CSI,  true, HIGHEST, 0,  384,  256,    0);
156         MBUS_CONF(      NAND,  true,    HIGH, 0,  100,   50,    0);
157         MBUS_CONF(        SS,  true,    HIGH, 0,  384,  256,    0);
158         MBUS_CONF(    DE_V3S, false,    HIGH, 0, 8192, 4096,    0);
159         MBUS_CONF(DE_CFD_V3S,  true,    HIGH, 0,  640,  256,    0);
160 }
161
162 static void mctl_set_master_priority_a64(void)
163 {
164         struct sunxi_mctl_com_reg * const mctl_com =
165                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
166
167         /* enable bandwidth limit windows and set windows size 1us */
168         writel(399, &mctl_com->tmr);
169         writel((1 << 16), &mctl_com->bwcr);
170
171         /* Port 2 is reserved per Allwinner's linux-3.10 source, yet they
172          * initialise it */
173         MBUS_CONF(   CPU,  true, HIGHEST, 0,  160,  100,   80);
174         MBUS_CONF(   GPU, false,    HIGH, 0, 1536, 1400,  256);
175         MBUS_CONF(UNUSED,  true, HIGHEST, 0,  512,  256,   96);
176         MBUS_CONF(   DMA,  true,    HIGH, 0,  256,   80,  100);
177         MBUS_CONF(    VE,  true,    HIGH, 0, 1792, 1600,  256);
178         MBUS_CONF(   CSI,  true,    HIGH, 0,  256,  128,    0);
179         MBUS_CONF(  NAND,  true,    HIGH, 0,  256,  128,   64);
180         MBUS_CONF(    SS,  true, HIGHEST, 0,  256,  128,   64);
181         MBUS_CONF(    TS,  true, HIGHEST, 0,  256,  128,   64);
182         MBUS_CONF(    DI,  true,    HIGH, 0, 1024,  256,   64);
183         MBUS_CONF(    DE,  true,    HIGH, 2, 8192, 6144, 2048);
184         MBUS_CONF(DE_CFD,  true,    HIGH, 0, 1280,  144,   64);
185
186         writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
187 }
188
189 static void mctl_set_master_priority_h5(void)
190 {
191         struct sunxi_mctl_com_reg * const mctl_com =
192                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
193
194         /* enable bandwidth limit windows and set windows size 1us */
195         writel(399, &mctl_com->tmr);
196         writel((1 << 16), &mctl_com->bwcr);
197
198         /* set cpu high priority */
199         writel(0x00000001, &mctl_com->mapr);
200
201         /* Port 2 is reserved per Allwinner's linux-3.10 source, yet
202          * they initialise it */
203         MBUS_CONF(   CPU, true, HIGHEST, 0,  300,  260,  150);
204         MBUS_CONF(   GPU, true, HIGHEST, 0,  600,  400,  200);
205         MBUS_CONF(UNUSED, true, HIGHEST, 0,  512,  256,   96);
206         MBUS_CONF(   DMA, true, HIGHEST, 0,  256,  128,   32);
207         MBUS_CONF(    VE, true, HIGHEST, 0, 1900, 1500, 1000);
208         MBUS_CONF(   CSI, true, HIGHEST, 0,  150,  120,  100);
209         MBUS_CONF(  NAND, true,    HIGH, 0,  256,  128,   64);
210         MBUS_CONF(    SS, true, HIGHEST, 0,  256,  128,   64);
211         MBUS_CONF(    TS, true, HIGHEST, 0,  256,  128,   64);
212         MBUS_CONF(    DI, true,    HIGH, 0, 1024,  256,   64);
213         MBUS_CONF(    DE, true, HIGHEST, 3, 3400, 2400, 1024);
214         MBUS_CONF(DE_CFD, true, HIGHEST, 0,  600,  400,  200);
215 }
216
217 static void mctl_set_master_priority_r40(void)
218 {
219         struct sunxi_mctl_com_reg * const mctl_com =
220                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
221
222         /* enable bandwidth limit windows and set windows size 1us */
223         writel(399, &mctl_com->tmr);
224         writel((1 << 16), &mctl_com->bwcr);
225
226         /* set cpu high priority */
227         writel(0x00000001, &mctl_com->mapr);
228
229         /* Port 2 is reserved per Allwinner's linux-3.10 source, yet
230          * they initialise it */
231         MBUS_CONF(     CPU, true, HIGHEST, 0,  300,  260,  150);
232         MBUS_CONF(     GPU, true, HIGHEST, 0,  600,  400,  200);
233         MBUS_CONF(  UNUSED, true, HIGHEST, 0,  512,  256,   96);
234         MBUS_CONF(     DMA, true, HIGHEST, 0,  256,  128,   32);
235         MBUS_CONF(      VE, true, HIGHEST, 0, 1900, 1500, 1000);
236         MBUS_CONF(     CSI, true, HIGHEST, 0,  150,  120,  100);
237         MBUS_CONF(    NAND, true,    HIGH, 0,  256,  128,   64);
238         MBUS_CONF(      SS, true, HIGHEST, 0,  256,  128,   64);
239         MBUS_CONF(      TS, true, HIGHEST, 0,  256,  128,   64);
240         MBUS_CONF(      DI, true,    HIGH, 0, 1024,  256,   64);
241
242         /*
243          * The port names are probably wrong, but no correct sources
244          * are available.
245          */
246         MBUS_CONF(      DE, true,    HIGH, 0,  128,   48,    0);
247         MBUS_CONF(  DE_CFD, true,    HIGH, 0,  384,  256,    0);
248         MBUS_CONF(UNKNOWN1, true, HIGHEST, 0,  512,  384,  256);
249         MBUS_CONF(UNKNOWN2, true, HIGHEST, 2, 8192, 6144, 1024);
250         MBUS_CONF(UNKNOWN3, true,    HIGH, 0, 1280,  144,   64);
251 }
252
253 static void mctl_set_master_priority(uint16_t socid)
254 {
255         switch (socid) {
256         case SOCID_H3:
257                 mctl_set_master_priority_h3();
258                 return;
259         case SOCID_V3S:
260                 mctl_set_master_priority_v3s();
261                 return;
262         case SOCID_A64:
263                 mctl_set_master_priority_a64();
264                 return;
265         case SOCID_H5:
266                 mctl_set_master_priority_h5();
267                 return;
268         case SOCID_R40:
269                 mctl_set_master_priority_r40();
270                 return;
271         }
272 }
273
274 static u32 bin_to_mgray(int val)
275 {
276         static const u8 lookup_table[32] = {
277                 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
278                 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
279                 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
280                 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
281         };
282
283         return lookup_table[clamp(val, 0, 31)];
284 }
285
286 static int mgray_to_bin(u32 val)
287 {
288         static const u8 lookup_table[32] = {
289                 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
290                 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
291                 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
292                 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
293         };
294
295         return lookup_table[val & 0x1f];
296 }
297
298 static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
299 {
300         struct sunxi_mctl_ctl_reg * const mctl_ctl =
301                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
302         int zq_count;
303
304 #if defined CONFIG_SUNXI_DRAM_DW_16BIT
305         zq_count = 4;
306 #else
307         zq_count = 6;
308 #endif
309
310         if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
311             (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
312                 u32 reg_val;
313
314                 clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
315                                 CONFIG_DRAM_ZQ & 0xffff);
316
317                 writel(PIR_CLRSR, &mctl_ctl->pir);
318                 mctl_phy_init(PIR_ZCAL);
319
320                 reg_val = readl(&mctl_ctl->zqdr[0]);
321                 reg_val &= (0x1f << 16) | (0x1f << 0);
322                 reg_val |= reg_val << 8;
323                 writel(reg_val, &mctl_ctl->zqdr[0]);
324
325                 reg_val = readl(&mctl_ctl->zqdr[1]);
326                 reg_val &= (0x1f << 16) | (0x1f << 0);
327                 reg_val |= reg_val << 8;
328                 writel(reg_val, &mctl_ctl->zqdr[1]);
329                 writel(reg_val, &mctl_ctl->zqdr[2]);
330         } else {
331                 int i;
332                 u16 zq_val[6];
333                 u8 val;
334
335                 writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
336
337                 for (i = 0; i < zq_count; i++) {
338                         u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
339
340                         writel((zq << 20) | (zq << 16) | (zq << 12) |
341                                         (zq << 8) | (zq << 4) | (zq << 0),
342                                         &mctl_ctl->zqcr);
343
344                         writel(PIR_CLRSR, &mctl_ctl->pir);
345                         mctl_phy_init(PIR_ZCAL);
346
347                         zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
348                         writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
349
350                         writel(PIR_CLRSR, &mctl_ctl->pir);
351                         mctl_phy_init(PIR_ZCAL);
352
353                         val = readl(&mctl_ctl->zqdr[0]) >> 24;
354                         zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
355                 }
356
357                 writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
358                 writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
359                 if (zq_count > 4)
360                         writel((zq_val[5] << 16) | zq_val[4],
361                                &mctl_ctl->zqdr[2]);
362         }
363 }
364
365 static void mctl_v3s_zq_calibration_quirk(struct dram_para *para)
366 {
367         struct sunxi_mctl_ctl_reg * const mctl_ctl =
368                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
369
370         u32 reg_val;
371
372         clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff,
373                         CONFIG_DRAM_ZQ & 0xffffff);
374         mctl_phy_init(PIR_ZCAL);
375
376         reg_val = readl(&mctl_ctl->zqdr[0]);
377         reg_val &= (0x1f << 16) | (0x1f << 0);
378         reg_val |= reg_val << 8;
379         writel(reg_val, &mctl_ctl->zqdr[0]);
380
381         reg_val = readl(&mctl_ctl->zqdr[1]);
382         reg_val &= (0x1f << 16) | (0x1f << 0);
383         reg_val |= reg_val << 8;
384         writel(reg_val, &mctl_ctl->zqdr[1]);
385 }
386
387 static void mctl_set_cr(uint16_t socid, struct dram_para *para)
388 {
389         struct sunxi_mctl_com_reg * const mctl_com =
390                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
391
392         writel(MCTL_CR_BL8 | MCTL_CR_INTERLEAVED |
393 #if defined CONFIG_SUNXI_DRAM_DDR3
394                MCTL_CR_DDR3 | MCTL_CR_2T |
395 #elif defined CONFIG_SUNXI_DRAM_DDR2
396                MCTL_CR_DDR2 | MCTL_CR_2T |
397 #elif defined CONFIG_SUNXI_DRAM_LPDDR3
398                MCTL_CR_LPDDR3 | MCTL_CR_1T |
399 #else
400 #error Unsupported DRAM type!
401 #endif
402                (para->ranks[0].bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) |
403                MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) |
404                (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
405                MCTL_CR_PAGE_SIZE(para->ranks[0].page_size) |
406                MCTL_CR_ROW_BITS(para->ranks[0].row_bits), &mctl_com->cr);
407
408         if (para->dual_rank && (socid == SOCID_A64 || socid == SOCID_R40)) {
409                 writel((para->ranks[1].bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) |
410                        MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) |
411                        MCTL_CR_DUAL_RANK |
412                        MCTL_CR_PAGE_SIZE(para->ranks[1].page_size) |
413                        MCTL_CR_ROW_BITS(para->ranks[1].row_bits), &mctl_com->cr_r1);
414         }
415
416         if (socid == SOCID_R40) {
417                 /* Mux pin to A15 address line for single rank memory. */
418                 if (!para->dual_rank)
419                         setbits_le32(&mctl_com->cr_r1, MCTL_CR_R1_MUX_A15);
420         }
421 }
422
423 static void mctl_sys_init(uint16_t socid, struct dram_para *para)
424 {
425         struct sunxi_ccm_reg * const ccm =
426                         (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
427         struct sunxi_mctl_ctl_reg * const mctl_ctl =
428                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
429
430         clrbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
431         clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
432         clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
433         clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
434         clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
435         if (socid == SOCID_A64 || socid == SOCID_R40)
436                 clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
437         udelay(10);
438
439         clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
440         udelay(1000);
441
442         if (socid == SOCID_A64 || socid == SOCID_R40) {
443                 clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
444                 clrsetbits_le32(&ccm->dram_clk_cfg,
445                                 CCM_DRAMCLK_CFG_DIV_MASK |
446                                 CCM_DRAMCLK_CFG_SRC_MASK,
447                                 CCM_DRAMCLK_CFG_DIV(1) |
448                                 CCM_DRAMCLK_CFG_SRC_PLL11 |
449                                 CCM_DRAMCLK_CFG_UPD);
450         } else if (socid == SOCID_H3 || socid == SOCID_H5 || socid == SOCID_V3S) {
451                 clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
452                 clrsetbits_le32(&ccm->dram_clk_cfg,
453                                 CCM_DRAMCLK_CFG_DIV_MASK |
454                                 CCM_DRAMCLK_CFG_SRC_MASK,
455                                 CCM_DRAMCLK_CFG_DIV(1) |
456                                 CCM_DRAMCLK_CFG_SRC_PLL5 |
457                                 CCM_DRAMCLK_CFG_UPD);
458         }
459         mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
460
461         setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
462         setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
463         setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
464         setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
465
466         setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
467         udelay(10);
468
469         writel(socid == SOCID_H5 ? 0x8000 : 0xc00e, &mctl_ctl->clken);
470         udelay(500);
471 }
472
473 /* These are more guessed based on some Allwinner code. */
474 #define DX_GCR_ODT_DYNAMIC      (0x0 << 4)
475 #define DX_GCR_ODT_ALWAYS_ON    (0x1 << 4)
476 #define DX_GCR_ODT_OFF          (0x2 << 4)
477
478 static int mctl_channel_init(uint16_t socid, struct dram_para *para)
479 {
480         struct sunxi_mctl_com_reg * const mctl_com =
481                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
482         struct sunxi_mctl_ctl_reg * const mctl_ctl =
483                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
484
485         unsigned int i;
486
487         mctl_set_cr(socid, para);
488         mctl_set_timing_params(socid, para);
489         mctl_set_master_priority(socid);
490
491         /* setting VTC, default disable all VT */
492         clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f);
493         if (socid == SOCID_H5)
494                 setbits_le32(&mctl_ctl->pgcr[1], (1 << 24) | (1 << 26));
495         else
496                 clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26);
497
498         /* increase DFI_PHY_UPD clock */
499         writel(PROTECT_MAGIC, &mctl_com->protect);
500         udelay(100);
501         clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16);
502         writel(0x0, &mctl_com->protect);
503         udelay(100);
504
505         /* set dramc odt */
506         for (i = 0; i < 4; i++) {
507                 u32 clearmask = (0x3 << 4) | (0x1 << 1) | (0x3 << 2) |
508                                 (0x3 << 12) | (0x3 << 14);
509                 u32 setmask = IS_ENABLED(CONFIG_DRAM_ODT_EN) ?
510                                 DX_GCR_ODT_DYNAMIC : DX_GCR_ODT_OFF;
511
512                 if (socid == SOCID_H5) {
513                         clearmask |= 0x2 << 8;
514                         setmask |= 0x4 << 8;
515                 }
516                 clrsetbits_le32(&mctl_ctl->dx[i].gcr, clearmask, setmask);
517         }
518
519         /* AC PDR should always ON */
520         clrsetbits_le32(&mctl_ctl->aciocr, socid == SOCID_H5 ? (0x1 << 11) : 0,
521                         0x1 << 1);
522
523         /* set DQS auto gating PD mode */
524         setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
525
526         if (socid == SOCID_H3) {
527                 /* dx ddr_clk & hdr_clk dynamic mode */
528                 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
529
530                 /* dphy & aphy phase select 270 degree */
531                 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
532                                 (0x1 << 10) | (0x2 << 8));
533         } else if (socid == SOCID_V3S) {
534                 /* dx ddr_clk & hdr_clk dynamic mode */
535                 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
536
537                 /* dphy & aphy phase select 270 degree */
538                 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
539                                 (0x1 << 10) | (0x1 << 8));
540         } else if (socid == SOCID_A64 || socid == SOCID_H5) {
541                 /* dphy & aphy phase select ? */
542                 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
543                                 (0x0 << 10) | (0x3 << 8));
544         } else if (socid == SOCID_R40) {
545                 /* dx ddr_clk & hdr_clk dynamic mode (tpr13[9] == 0) */
546                 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
547
548                 /* dphy & aphy phase select ? */
549                 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
550                                 (0x0 << 10) | (0x3 << 8));
551         }
552
553         /* set half DQ */
554         if (!para->bus_full_width) {
555 #if defined CONFIG_SUNXI_DRAM_DW_32BIT
556                 writel(0x0, &mctl_ctl->dx[2].gcr);
557                 writel(0x0, &mctl_ctl->dx[3].gcr);
558 #elif defined CONFIG_SUNXI_DRAM_DW_16BIT
559                 writel(0x0, &mctl_ctl->dx[1].gcr);
560 #else
561 #error Unsupported DRAM bus width!
562 #endif
563         }
564
565         /* data training configuration */
566         clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24,
567                         (para->dual_rank ? 0x3 : 0x1) << 24);
568
569         mctl_set_bit_delays(para);
570         udelay(50);
571
572         if (socid == SOCID_V3S) {
573                 mctl_v3s_zq_calibration_quirk(para);
574
575                 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
576                               PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
577         } else if (socid == SOCID_H3) {
578                 mctl_h3_zq_calibration_quirk(para);
579
580                 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
581                               PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
582         } else if (socid == SOCID_A64 || socid == SOCID_H5) {
583                 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
584
585                 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
586                               PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
587                 /* no PIR_QSGATE for H5 ???? */
588         } else if (socid == SOCID_R40) {
589                 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
590
591                 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
592                               PIR_DRAMRST | PIR_DRAMINIT);
593         }
594
595         /* detect ranks and bus width */
596         if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
597                 /* only one rank */
598                 if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2)
599 #if defined CONFIG_SUNXI_DRAM_DW_32BIT
600                     || ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)
601 #endif
602                     ) {
603                         clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
604                         para->dual_rank = 0;
605                 }
606
607                 /* only half DQ width */
608 #if defined CONFIG_SUNXI_DRAM_DW_32BIT
609                 if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) ||
610                     ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) {
611                         writel(0x0, &mctl_ctl->dx[2].gcr);
612                         writel(0x0, &mctl_ctl->dx[3].gcr);
613                         para->bus_full_width = 0;
614                 }
615 #elif defined CONFIG_SUNXI_DRAM_DW_16BIT
616                 if ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x1) {
617                         writel(0x0, &mctl_ctl->dx[1].gcr);
618                         para->bus_full_width = 0;
619                 }
620 #endif
621
622                 mctl_set_cr(socid, para);
623                 udelay(20);
624
625                 /* re-train */
626                 mctl_phy_init(PIR_QSGATE);
627                 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
628                         return 1;
629         }
630
631         /* check the dramc status */
632         mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
633
634         /* liuke added for refresh debug */
635         setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
636         udelay(10);
637         clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
638         udelay(10);
639
640         /* set PGCR3, CKE polarity */
641         if (socid == SOCID_H3 || socid == SOCID_V3S)
642                 writel(0x00aa0060, &mctl_ctl->pgcr[3]);
643         else if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40)
644                 writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
645
646         /* power down zq calibration module for power save */
647         setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
648
649         /* enable master access */
650         writel(0xffffffff, &mctl_com->maer);
651
652         return 0;
653 }
654
655 /*
656  * Test if memory at offset offset matches memory at a certain base
657  */
658 static bool mctl_mem_matches_base(u32 offset, ulong base)
659 {
660         /* Try to write different values to RAM at two addresses */
661         writel(0, base);
662         writel(0xaa55aa55, base + offset);
663         dsb();
664         /* Check if the same value is actually observed when reading back */
665         return readl(base) ==
666                readl(base + offset);
667 }
668
669 static void mctl_auto_detect_dram_size_rank(uint16_t socid, struct dram_para *para, ulong base, struct rank_para *rank)
670 {
671         /* detect row address bits */
672         rank->page_size = 512;
673         rank->row_bits = 16;
674         rank->bank_bits = 2;
675         mctl_set_cr(socid, para);
676
677         for (rank->row_bits = 11; rank->row_bits < 16; rank->row_bits++)
678                 if (mctl_mem_matches_base((1 << (rank->row_bits + rank->bank_bits)) * rank->page_size, base))
679                         break;
680
681         /* detect bank address bits */
682         rank->bank_bits = 3;
683         mctl_set_cr(socid, para);
684
685         for (rank->bank_bits = 2; rank->bank_bits < 3; rank->bank_bits++)
686                 if (mctl_mem_matches_base((1 << rank->bank_bits) * rank->page_size, base))
687                         break;
688
689         /* detect page size */
690         rank->page_size = 8192;
691         mctl_set_cr(socid, para);
692
693         for (rank->page_size = 512; rank->page_size < 8192; rank->page_size *= 2)
694                 if (mctl_mem_matches_base(rank->page_size, base))
695                         break;
696 }
697
698 static unsigned long mctl_calc_rank_size(struct rank_para *rank)
699 {
700         return (1UL << (rank->row_bits + rank->bank_bits)) * rank->page_size;
701 }
702
703 /*
704  * Because we cannot do mctl_phy_init(PIR_QSGATE) on R40 now (which leads
705  * to failure), it's needed to detect the rank count of R40 in another way.
706  *
707  * The code here is modelled after time_out_detect() in BSP, which tries to
708  * access the memory and check for error code.
709  *
710  * TODO: auto detect half DQ width here
711  */
712 static void mctl_r40_detect_rank_count(struct dram_para *para)
713 {
714         ulong rank1_base = (ulong) CONFIG_SYS_SDRAM_BASE +
715                            mctl_calc_rank_size(&para->ranks[0]);
716         struct sunxi_mctl_ctl_reg * const mctl_ctl =
717                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
718
719         /* Enable read time out */
720         setbits_le32(&mctl_ctl->pgcr[0], 0x1 << 25);
721
722         (void) readl((void *) rank1_base);
723         udelay(10);
724
725         if (readl(&mctl_ctl->pgsr[0]) & (0x1 << 13)) {
726                 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
727                 para->dual_rank = 0;
728         }
729
730         /* Reset PHY FIFO to clear it */
731         clrbits_le32(&mctl_ctl->pgcr[0], 0x1 << 26);
732         udelay(100);
733         setbits_le32(&mctl_ctl->pgcr[0], 0x1 << 26);
734
735         /* Clear error status */
736         setbits_le32(&mctl_ctl->pgcr[0], 0x1 << 24);
737
738         /* Clear time out flag */
739         clrbits_le32(&mctl_ctl->pgsr[0], 0x1 << 13);
740
741         /* Disable read time out */
742         clrbits_le32(&mctl_ctl->pgcr[0], 0x1 << 25);
743 }
744
745 static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para)
746 {
747         mctl_auto_detect_dram_size_rank(socid, para, (ulong)CONFIG_SYS_SDRAM_BASE, &para->ranks[0]);
748
749         if ((socid == SOCID_A64 || socid == SOCID_R40) && para->dual_rank) {
750                 mctl_auto_detect_dram_size_rank(socid, para, (ulong)CONFIG_SYS_SDRAM_BASE + mctl_calc_rank_size(&para->ranks[0]), &para->ranks[1]);
751         }
752 }
753
754 /*
755  * The actual values used here are taken from Allwinner provided boot0
756  * binaries, though they are probably board specific, so would likely benefit
757  * from invidual tuning for each board. Apparently a lot of boards copy from
758  * some Allwinner reference design, so we go with those generic values for now
759  * in the hope that they are reasonable for most (all?) boards.
760  */
761 #define SUN8I_H3_DX_READ_DELAYS                                 \
762         {{ 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },        \
763          { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },        \
764          { 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },        \
765          { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 }}
766 #define SUN8I_H3_DX_WRITE_DELAYS                                \
767         {{  0,  0,  0,  0,  0,  0,  0,  0,  0, 10, 10 },        \
768          {  0,  0,  0,  0,  0,  0,  0,  0,  0, 10, 10 },        \
769          {  0,  0,  0,  0,  0,  0,  0,  0,  0, 10, 10 },        \
770          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  6 }}
771 #define SUN8I_H3_AC_DELAYS                                      \
772         {  0,  0,  0,  0,  0,  0,  0,  0,                       \
773            0,  0,  0,  0,  0,  0,  0,  0,                       \
774            0,  0,  0,  0,  0,  0,  0,  0,                       \
775            0,  0,  0,  0,  0,  0,  0      }
776
777 #define SUN8I_V3S_DX_READ_DELAYS                                        \
778         {{  8,  8,  8,  8,  8,  8,  8,  8,  8,  0,  0 },        \
779          {  7,  7,  7,  7,  7,  7,  7,  7,  7,  0,  0 },        \
780          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },        \
781          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
782 #define SUN8I_V3S_DX_WRITE_DELAYS                               \
783         {{  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  4 },        \
784          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2 },        \
785          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },        \
786          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
787 #define SUN8I_V3S_AC_DELAYS                                     \
788         {  0,  0,  0,  0,  0,  0,  0,  0,                       \
789            0,  0,  0,  0,  0,  0,  0,  0,                       \
790            0,  0,  0,  0,  0,  0,  0,  0,                       \
791            0,  0,  0,  0,  0,  0,  0      }
792
793 #define SUN8I_R40_DX_READ_DELAYS                                \
794         {{ 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },        \
795          { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },        \
796          { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },        \
797          { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 } }
798 #define SUN8I_R40_DX_WRITE_DELAYS                               \
799         {{  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0 },        \
800          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0 },        \
801          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0 },        \
802          {  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0 } }
803 #define SUN8I_R40_AC_DELAYS                                     \
804         {  0,  0,  3,  0,  0,  0,  0,  0,                       \
805            0,  0,  0,  0,  0,  0,  0,  0,                       \
806            0,  0,  0,  0,  0,  0,  0,  0,                       \
807            0,  0,  0,  0,  0,  0,  0      }
808
809 #define SUN50I_A64_DX_READ_DELAYS                               \
810         {{ 16, 16, 16, 16, 17, 16, 16, 17, 16,  1,  0 },        \
811          { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 },        \
812          { 16, 17, 17, 16, 16, 16, 16, 16, 16,  0,  0 },        \
813          { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 }}
814 #define SUN50I_A64_DX_WRITE_DELAYS                              \
815         {{  0,  0,  0,  0,  0,  0,  0,  0,  0, 15, 15 },        \
816          {  0,  0,  0,  0,  1,  1,  1,  1,  0, 10, 10 },        \
817          {  1,  0,  1,  1,  1,  1,  1,  1,  0, 11, 11 },        \
818          {  1,  0,  0,  1,  1,  1,  1,  1,  0, 12, 12 }}
819 #define SUN50I_A64_AC_DELAYS                                    \
820         {  5,  5, 13, 10,  2,  5,  3,  3,                       \
821            0,  3,  3,  3,  1,  0,  0,  0,                       \
822            3,  4,  0,  3,  4,  1,  4,  0,                       \
823            1,  1,  0,  1, 13,  5,  4      }
824
825 #define SUN8I_H5_DX_READ_DELAYS                                 \
826         {{ 14, 15, 17, 17, 17, 17, 17, 18, 17,  3,  3 },        \
827          { 21, 21, 12, 22, 21, 21, 21, 21, 21,  3,  3 },        \
828          { 16, 19, 19, 17, 22, 22, 21, 22, 19,  3,  3 },        \
829          { 21, 21, 22, 22, 20, 21, 19, 19, 19,  3,  3 } }
830 #define SUN8I_H5_DX_WRITE_DELAYS                                \
831         {{  1,  2,  3,  4,  3,  4,  4,  4,  6,  6,  6 },        \
832          {  6,  6,  6,  5,  5,  5,  5,  5,  6,  6,  6 },        \
833          {  0,  2,  4,  2,  6,  5,  5,  5,  6,  6,  6 },        \
834          {  3,  3,  3,  2,  2,  1,  1,  1,  4,  4,  4 } }
835 #define SUN8I_H5_AC_DELAYS                                      \
836         {  0,  0,  5,  5,  0,  0,  0,  0,                       \
837            0,  0,  0,  0,  3,  3,  3,  3,                       \
838            3,  3,  3,  3,  3,  3,  3,  3,                       \
839            3,  3,  3,  3,  2,  0,  0      }
840
841 unsigned long sunxi_dram_init(void)
842 {
843         struct sunxi_mctl_com_reg * const mctl_com =
844                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
845         struct sunxi_mctl_ctl_reg * const mctl_ctl =
846                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
847
848         unsigned long size;
849
850         struct dram_para para = {
851                 .dual_rank = 1,
852                 .bus_full_width = 1,
853                 .ranks = {
854                         {
855                                 .row_bits = 15,
856                                 .bank_bits = 3,
857                                 .page_size = 4096,
858                         },
859                         {
860                                 .row_bits = 15,
861                                 .bank_bits = 3,
862                                 .page_size = 4096,
863                         }
864                 },
865
866 #if defined(CONFIG_MACH_SUN8I_H3)
867                 .dx_read_delays  = SUN8I_H3_DX_READ_DELAYS,
868                 .dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS,
869                 .ac_delays       = SUN8I_H3_AC_DELAYS,
870 #elif defined(CONFIG_MACH_SUN8I_V3S)
871                 .dx_read_delays  = SUN8I_V3S_DX_READ_DELAYS,
872                 .dx_write_delays = SUN8I_V3S_DX_WRITE_DELAYS,
873                 .ac_delays       = SUN8I_V3S_AC_DELAYS,
874 #elif defined(CONFIG_MACH_SUN8I_R40)
875                 .dx_read_delays  = SUN8I_R40_DX_READ_DELAYS,
876                 .dx_write_delays = SUN8I_R40_DX_WRITE_DELAYS,
877                 .ac_delays       = SUN8I_R40_AC_DELAYS,
878 #elif defined(CONFIG_MACH_SUN50I)
879                 .dx_read_delays  = SUN50I_A64_DX_READ_DELAYS,
880                 .dx_write_delays = SUN50I_A64_DX_WRITE_DELAYS,
881                 .ac_delays       = SUN50I_A64_AC_DELAYS,
882 #elif defined(CONFIG_MACH_SUN50I_H5)
883                 .dx_read_delays  = SUN8I_H5_DX_READ_DELAYS,
884                 .dx_write_delays = SUN8I_H5_DX_WRITE_DELAYS,
885                 .ac_delays       = SUN8I_H5_AC_DELAYS,
886 #endif
887         };
888 /*
889  * Let the compiler optimize alternatives away by passing this value into
890  * the static functions. This saves us #ifdefs, but still keeps the binary
891  * small.
892  */
893 #if defined(CONFIG_MACH_SUN8I_H3)
894         uint16_t socid = SOCID_H3;
895 #elif defined(CONFIG_MACH_SUN8I_R40)
896         uint16_t socid = SOCID_R40;
897 #elif defined(CONFIG_MACH_SUN8I_V3S)
898         uint16_t socid = SOCID_V3S;
899 #elif defined(CONFIG_MACH_SUN50I)
900         uint16_t socid = SOCID_A64;
901 #elif defined(CONFIG_MACH_SUN50I_H5)
902         uint16_t socid = SOCID_H5;
903 #endif
904
905         mctl_sys_init(socid, &para);
906         if (mctl_channel_init(socid, &para))
907                 return 0;
908
909         if (para.dual_rank)
910                 writel(0x00000303, &mctl_ctl->odtmap);
911         else
912                 writel(0x00000201, &mctl_ctl->odtmap);
913         udelay(1);
914
915         /* odt delay */
916         if (socid == SOCID_H3)
917                 writel(0x0c000400, &mctl_ctl->odtcfg);
918
919         if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40) {
920                 /* VTF enable (tpr13[8] == 1) */
921                 setbits_le32(&mctl_ctl->vtfcr,
922                              (socid != SOCID_A64 ? 3 : 2) << 8);
923                 /* DQ hold disable (tpr13[26] == 1) */
924                 clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
925         }
926
927         /* clear credit value */
928         setbits_le32(&mctl_com->cccr, 1 << 31);
929         udelay(10);
930
931         if (socid == SOCID_R40) {
932                 mctl_r40_detect_rank_count(&para);
933                 mctl_set_cr(SOCID_R40, &para);
934         }
935
936         mctl_auto_detect_dram_size(socid, &para);
937         mctl_set_cr(socid, &para);
938
939         size = mctl_calc_rank_size(&para.ranks[0]);
940         if (socid == SOCID_A64 || socid == SOCID_R40) {
941                 if (para.dual_rank)
942                         size += mctl_calc_rank_size(&para.ranks[1]);
943         } else if (para.dual_rank) {
944                 size *= 2;
945         }
946
947         return size;
948 }