2 * sun8i H3 platform dram controller init
4 * (C) Copyright 2007-2015 Allwinner Technology Co.
5 * Jerry Wang <wangflord@allwinnertech.com>
6 * (C) Copyright 2015 Vishnu Patekar <vishnupatekar0510@gmail.com>
7 * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
8 * (C) Copyright 2015 Jens Kuske <jenskuske@gmail.com>
10 * SPDX-License-Identifier: GPL-2.0+
14 #include <asm/arch/clock.h>
15 #include <asm/arch/dram.h>
16 #include <asm/arch/cpu.h>
17 #include <linux/kconfig.h>
20 * The delay parameters below allow to allegedly specify delay times of some
21 * unknown unit for each individual bit trace in each of the four data bytes
22 * the 32-bit wide access consists of. Also three control signals can be
23 * adjusted individually.
25 #define BITS_PER_BYTE 8
26 #define NR_OF_BYTE_LANES (32 / BITS_PER_BYTE)
27 /* The eight data lines (DQn) plus DM, DQS and DQSN */
28 #define LINES_PER_BYTE_LANE (BITS_PER_BYTE + 3)
34 const u8 dx_read_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE];
35 const u8 dx_write_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE];
36 const u8 ac_delays[31];
39 static inline int ns_to_t(int nanoseconds)
41 const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
43 return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
46 static void mctl_phy_init(u32 val)
48 struct sunxi_mctl_ctl_reg * const mctl_ctl =
49 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
51 writel(val | PIR_INIT, &mctl_ctl->pir);
52 mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1);
55 static void mctl_set_bit_delays(struct dram_para *para)
57 struct sunxi_mctl_ctl_reg * const mctl_ctl =
58 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
61 clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
63 for (i = 0; i < NR_OF_BYTE_LANES; i++)
64 for (j = 0; j < LINES_PER_BYTE_LANE; j++)
65 writel(DXBDLR_WRITE_DELAY(para->dx_write_delays[i][j]) |
66 DXBDLR_READ_DELAY(para->dx_read_delays[i][j]),
67 &mctl_ctl->dx[i].bdlr[j]);
69 for (i = 0; i < 31; i++)
70 writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
71 &mctl_ctl->acbdlr[i]);
73 setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
88 MBUS_PORT_DE_CFD = 11,
98 inline void mbus_configure_port(u8 port,
101 u8 qos, /* MBUS_QOS_LOWEST .. MBUS_QOS_HIGEST */
102 u8 waittime, /* 0 .. 0xf */
103 u8 acs, /* 0 .. 0xff */
104 u16 bwl0, /* 0 .. 0xffff, bandwidth limit in MB/s */
108 struct sunxi_mctl_com_reg * const mctl_com =
109 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
111 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
112 | (priority ? (1 << 1) : 0)
114 | ((waittime & 0xf) << 4)
115 | ((acs & 0xff) << 8)
117 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
119 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
120 writel(cfg0, &mctl_com->mcr[port][0]);
121 writel(cfg1, &mctl_com->mcr[port][1]);
124 #define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
125 mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
126 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
128 static void mctl_set_master_priority_h3(void)
130 struct sunxi_mctl_com_reg * const mctl_com =
131 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
133 /* enable bandwidth limit windows and set windows size 1us */
134 writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
136 /* set cpu high priority */
137 writel(0x00000001, &mctl_com->mapr);
139 MBUS_CONF( CPU, true, HIGHEST, 0, 512, 256, 128);
140 MBUS_CONF( GPU, true, HIGH, 0, 1536, 1024, 256);
141 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
142 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
143 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
144 MBUS_CONF( CSI, true, HIGHEST, 0, 256, 128, 32);
145 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
146 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
147 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
148 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
149 MBUS_CONF( DE, true, HIGHEST, 3, 8192, 6120, 1024);
150 MBUS_CONF(DE_CFD, true, HIGH, 0, 1024, 288, 64);
153 static void mctl_set_master_priority_a64(void)
155 struct sunxi_mctl_com_reg * const mctl_com =
156 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
158 /* enable bandwidth limit windows and set windows size 1us */
159 writel(399, &mctl_com->tmr);
160 writel((1 << 16), &mctl_com->bwcr);
162 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet they
164 MBUS_CONF( CPU, true, HIGHEST, 0, 160, 100, 80);
165 MBUS_CONF( GPU, false, HIGH, 0, 1536, 1400, 256);
166 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
167 MBUS_CONF( DMA, true, HIGH, 0, 256, 80, 100);
168 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
169 MBUS_CONF( CSI, true, HIGH, 0, 256, 128, 0);
170 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
171 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
172 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
173 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
174 MBUS_CONF( DE, true, HIGH, 2, 8192, 6144, 2048);
175 MBUS_CONF(DE_CFD, true, HIGH, 0, 1280, 144, 64);
177 writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
180 static void mctl_set_master_priority(uint16_t socid)
184 mctl_set_master_priority_h3();
187 mctl_set_master_priority_a64();
192 static void mctl_set_timing_params(uint16_t socid, struct dram_para *para)
194 struct sunxi_mctl_ctl_reg * const mctl_ctl =
195 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
198 u8 tfaw = ns_to_t(50);
199 u8 trrd = max(ns_to_t(10), 4);
200 u8 trcd = ns_to_t(15);
201 u8 trc = ns_to_t(53);
202 u8 txp = max(ns_to_t(8), 3);
203 u8 twtr = max(ns_to_t(8), 4);
204 u8 trtp = max(ns_to_t(8), 4);
205 u8 twr = max(ns_to_t(15), 3);
206 u8 trp = ns_to_t(15);
207 u8 tras = ns_to_t(38);
208 u16 trefi = ns_to_t(7800) / 32;
209 u16 trfc = ns_to_t(350);
220 u8 tcl = 6; /* CL 12 */
221 u8 tcwl = 4; /* CWL 8 */
225 u32 tdinit0 = (500 * CONFIG_DRAM_CLK) + 1; /* 500us */
226 u32 tdinit1 = (360 * CONFIG_DRAM_CLK) / 1000 + 1; /* 360ns */
227 u32 tdinit2 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */
228 u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */
230 u8 twtp = tcwl + 2 + twr; /* WL + BL / 2 + tWR */
231 u8 twr2rd = tcwl + 2 + twtr; /* WL + BL / 2 + tWTR */
232 u8 trd2wr = tcl + 2 + 1 - tcwl; /* RL + BL / 2 + 2 - WL */
234 /* set mode register */
235 writel(0x1c70, &mctl_ctl->mr[0]); /* CL=11, WR=12 */
236 writel(0x40, &mctl_ctl->mr[1]);
237 writel(0x18, &mctl_ctl->mr[2]); /* CWL=8 */
238 writel(0x0, &mctl_ctl->mr[3]);
240 /* set DRAM timing */
241 writel(DRAMTMG0_TWTP(twtp) | DRAMTMG0_TFAW(tfaw) |
242 DRAMTMG0_TRAS_MAX(trasmax) | DRAMTMG0_TRAS(tras),
243 &mctl_ctl->dramtmg[0]);
244 writel(DRAMTMG1_TXP(txp) | DRAMTMG1_TRTP(trtp) | DRAMTMG1_TRC(trc),
245 &mctl_ctl->dramtmg[1]);
246 writel(DRAMTMG2_TCWL(tcwl) | DRAMTMG2_TCL(tcl) |
247 DRAMTMG2_TRD2WR(trd2wr) | DRAMTMG2_TWR2RD(twr2rd),
248 &mctl_ctl->dramtmg[2]);
249 writel(DRAMTMG3_TMRW(tmrw) | DRAMTMG3_TMRD(tmrd) | DRAMTMG3_TMOD(tmod),
250 &mctl_ctl->dramtmg[3]);
251 writel(DRAMTMG4_TRCD(trcd) | DRAMTMG4_TCCD(tccd) | DRAMTMG4_TRRD(trrd) |
252 DRAMTMG4_TRP(trp), &mctl_ctl->dramtmg[4]);
253 writel(DRAMTMG5_TCKSRX(tcksrx) | DRAMTMG5_TCKSRE(tcksre) |
254 DRAMTMG5_TCKESR(tckesr) | DRAMTMG5_TCKE(tcke),
255 &mctl_ctl->dramtmg[5]);
257 /* set two rank timing */
258 clrsetbits_le32(&mctl_ctl->dramtmg[8], (0xff << 8) | (0xff << 0),
259 (0x66 << 8) | (0x10 << 0));
261 /* set PHY interface timing, write latency and read latency configure */
262 writel((0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) |
263 (wr_latency << 0), &mctl_ctl->pitmg[0]);
265 /* set PHY timing, PTR0-2 use default */
266 writel(PTR3_TDINIT0(tdinit0) | PTR3_TDINIT1(tdinit1), &mctl_ctl->ptr[3]);
267 writel(PTR4_TDINIT2(tdinit2) | PTR4_TDINIT3(tdinit3), &mctl_ctl->ptr[4]);
269 /* set refresh timing */
270 writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg);
273 static u32 bin_to_mgray(int val)
275 static const u8 lookup_table[32] = {
276 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
277 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
278 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
279 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
282 return lookup_table[clamp(val, 0, 31)];
285 static int mgray_to_bin(u32 val)
287 static const u8 lookup_table[32] = {
288 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
289 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
290 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
291 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
294 return lookup_table[val & 0x1f];
297 static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
299 struct sunxi_mctl_ctl_reg * const mctl_ctl =
300 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
302 if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
303 (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
306 clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
307 CONFIG_DRAM_ZQ & 0xffff);
309 writel(PIR_CLRSR, &mctl_ctl->pir);
310 mctl_phy_init(PIR_ZCAL);
312 reg_val = readl(&mctl_ctl->zqdr[0]);
313 reg_val &= (0x1f << 16) | (0x1f << 0);
314 reg_val |= reg_val << 8;
315 writel(reg_val, &mctl_ctl->zqdr[0]);
317 reg_val = readl(&mctl_ctl->zqdr[1]);
318 reg_val &= (0x1f << 16) | (0x1f << 0);
319 reg_val |= reg_val << 8;
320 writel(reg_val, &mctl_ctl->zqdr[1]);
321 writel(reg_val, &mctl_ctl->zqdr[2]);
327 writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
329 for (i = 0; i < 6; i++) {
330 u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
332 writel((zq << 20) | (zq << 16) | (zq << 12) |
333 (zq << 8) | (zq << 4) | (zq << 0),
336 writel(PIR_CLRSR, &mctl_ctl->pir);
337 mctl_phy_init(PIR_ZCAL);
339 zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
340 writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
342 writel(PIR_CLRSR, &mctl_ctl->pir);
343 mctl_phy_init(PIR_ZCAL);
345 val = readl(&mctl_ctl->zqdr[0]) >> 24;
346 zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
349 writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
350 writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
351 writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
355 static void mctl_set_cr(struct dram_para *para)
357 struct sunxi_mctl_com_reg * const mctl_com =
358 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
360 writel(MCTL_CR_BL8 | MCTL_CR_2T | MCTL_CR_DDR3 | MCTL_CR_INTERLEAVED |
361 MCTL_CR_EIGHT_BANKS | MCTL_CR_BUS_WIDTH(para->bus_width) |
362 (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
363 MCTL_CR_PAGE_SIZE(para->page_size) |
364 MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr);
367 static void mctl_sys_init(uint16_t socid, struct dram_para *para)
369 struct sunxi_ccm_reg * const ccm =
370 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
371 struct sunxi_mctl_ctl_reg * const mctl_ctl =
372 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
374 clrbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
375 clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
376 clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
377 clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
378 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
379 if (socid == SOCID_A64)
380 clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
383 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
386 if (socid == SOCID_A64) {
387 clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
388 clrsetbits_le32(&ccm->dram_clk_cfg,
389 CCM_DRAMCLK_CFG_DIV_MASK |
390 CCM_DRAMCLK_CFG_SRC_MASK,
391 CCM_DRAMCLK_CFG_DIV(1) |
392 CCM_DRAMCLK_CFG_SRC_PLL11 |
393 CCM_DRAMCLK_CFG_UPD);
394 } else if (socid == SOCID_H3) {
395 clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
396 clrsetbits_le32(&ccm->dram_clk_cfg,
397 CCM_DRAMCLK_CFG_DIV_MASK |
398 CCM_DRAMCLK_CFG_SRC_MASK,
399 CCM_DRAMCLK_CFG_DIV(1) |
400 CCM_DRAMCLK_CFG_SRC_PLL5 |
401 CCM_DRAMCLK_CFG_UPD);
403 mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
405 setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
406 setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
407 setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
408 setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
410 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
413 writel(0xc00e, &mctl_ctl->clken);
417 static int mctl_channel_init(uint16_t socid, struct dram_para *para)
419 struct sunxi_mctl_com_reg * const mctl_com =
420 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
421 struct sunxi_mctl_ctl_reg * const mctl_ctl =
422 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
427 mctl_set_timing_params(socid, para);
428 mctl_set_master_priority(socid);
430 /* setting VTC, default disable all VT */
431 clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f);
432 clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26);
434 /* increase DFI_PHY_UPD clock */
435 writel(PROTECT_MAGIC, &mctl_com->protect);
437 clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16);
438 writel(0x0, &mctl_com->protect);
442 for (i = 0; i < 4; i++)
443 clrsetbits_le32(&mctl_ctl->dx[i].gcr, (0x3 << 4) |
444 (0x1 << 1) | (0x3 << 2) | (0x3 << 12) |
446 IS_ENABLED(CONFIG_DRAM_ODT_EN) ? 0x0 : 0x2);
448 /* AC PDR should always ON */
449 setbits_le32(&mctl_ctl->aciocr, 0x1 << 1);
451 /* set DQS auto gating PD mode */
452 setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
454 if (socid == SOCID_H3) {
455 /* dx ddr_clk & hdr_clk dynamic mode */
456 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
458 /* dphy & aphy phase select 270 degree */
459 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
460 (0x1 << 10) | (0x2 << 8));
461 } else if (socid == SOCID_A64) {
462 /* dphy & aphy phase select ? */
463 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
464 (0x0 << 10) | (0x3 << 8));
468 if (para->bus_width != 32) {
469 writel(0x0, &mctl_ctl->dx[2].gcr);
470 writel(0x0, &mctl_ctl->dx[3].gcr);
473 /* data training configuration */
474 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24,
475 (para->dual_rank ? 0x3 : 0x1) << 24);
477 mctl_set_bit_delays(para);
480 if (socid == SOCID_H3) {
481 mctl_h3_zq_calibration_quirk(para);
483 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
484 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
485 } else if (socid == SOCID_A64) {
486 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
488 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
489 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
492 /* detect ranks and bus width */
493 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
495 if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2) ||
496 ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)) {
497 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
501 /* only half DQ width */
502 if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) ||
503 ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) {
504 writel(0x0, &mctl_ctl->dx[2].gcr);
505 writel(0x0, &mctl_ctl->dx[3].gcr);
506 para->bus_width = 16;
513 mctl_phy_init(PIR_QSGATE);
514 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
518 /* check the dramc status */
519 mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
521 /* liuke added for refresh debug */
522 setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
524 clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
527 /* set PGCR3, CKE polarity */
528 if (socid == SOCID_H3)
529 writel(0x00aa0060, &mctl_ctl->pgcr[3]);
530 else if (socid == SOCID_A64)
531 writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
533 /* power down zq calibration module for power save */
534 setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
536 /* enable master access */
537 writel(0xffffffff, &mctl_com->maer);
542 static void mctl_auto_detect_dram_size(struct dram_para *para)
544 /* detect row address bits */
545 para->page_size = 512;
549 for (para->row_bits = 11; para->row_bits < 16; para->row_bits++)
550 if (mctl_mem_matches((1 << (para->row_bits + 3)) * para->page_size))
553 /* detect page size */
554 para->page_size = 8192;
557 for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2)
558 if (mctl_mem_matches(para->page_size))
563 * The actual values used here are taken from Allwinner provided boot0
564 * binaries, though they are probably board specific, so would likely benefit
565 * from invidual tuning for each board. Apparently a lot of boards copy from
566 * some Allwinner reference design, so we go with those generic values for now
567 * in the hope that they are reasonable for most (all?) boards.
569 #define SUN8I_H3_DX_READ_DELAYS \
570 {{ 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
571 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
572 { 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
573 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }}
574 #define SUN8I_H3_DX_WRITE_DELAYS \
575 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
576 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
577 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
578 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 }}
579 #define SUN8I_H3_AC_DELAYS \
580 { 0, 0, 0, 0, 0, 0, 0, 0, \
581 0, 0, 0, 0, 0, 0, 0, 0, \
582 0, 0, 0, 0, 0, 0, 0, 0, \
583 0, 0, 0, 0, 0, 0, 0 }
585 #define SUN50I_A64_DX_READ_DELAYS \
586 {{ 16, 16, 16, 16, 17, 16, 16, 17, 16, 1, 0 }, \
587 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }, \
588 { 16, 17, 17, 16, 16, 16, 16, 16, 16, 0, 0 }, \
589 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }}
590 #define SUN50I_A64_DX_WRITE_DELAYS \
591 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15 }, \
592 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 10, 10 }, \
593 { 1, 0, 1, 1, 1, 1, 1, 1, 0, 11, 11 }, \
594 { 1, 0, 0, 1, 1, 1, 1, 1, 0, 12, 12 }}
595 #define SUN50I_A64_AC_DELAYS \
596 { 5, 5, 13, 10, 2, 5, 3, 3, \
597 0, 3, 3, 3, 1, 0, 0, 0, \
598 3, 4, 0, 3, 4, 1, 4, 0, \
599 1, 1, 0, 1, 13, 5, 4 }
601 unsigned long sunxi_dram_init(void)
603 struct sunxi_mctl_com_reg * const mctl_com =
604 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
605 struct sunxi_mctl_ctl_reg * const mctl_ctl =
606 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
608 struct dram_para para = {
614 #if defined(CONFIG_MACH_SUN8I_H3)
615 .dx_read_delays = SUN8I_H3_DX_READ_DELAYS,
616 .dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS,
617 .ac_delays = SUN8I_H3_AC_DELAYS,
618 #elif defined(CONFIG_MACH_SUN50I)
619 .dx_read_delays = SUN50I_A64_DX_READ_DELAYS,
620 .dx_write_delays = SUN50I_A64_DX_WRITE_DELAYS,
621 .ac_delays = SUN50I_A64_AC_DELAYS,
625 * Let the compiler optimize alternatives away by passing this value into
626 * the static functions. This saves us #ifdefs, but still keeps the binary
629 #if defined(CONFIG_MACH_SUN8I_H3)
630 uint16_t socid = SOCID_H3;
631 #elif defined(CONFIG_MACH_SUN50I)
632 uint16_t socid = SOCID_A64;
635 mctl_sys_init(socid, ¶);
636 if (mctl_channel_init(socid, ¶))
640 writel(0x00000303, &mctl_ctl->odtmap);
642 writel(0x00000201, &mctl_ctl->odtmap);
646 if (socid == SOCID_H3)
647 writel(0x0c000400, &mctl_ctl->odtcfg);
649 if (socid == SOCID_A64) {
650 setbits_le32(&mctl_ctl->vtfcr, 2 << 8);
651 clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
654 /* clear credit value */
655 setbits_le32(&mctl_com->cccr, 1 << 31);
658 mctl_auto_detect_dram_size(¶);
661 return (1 << (para.row_bits + 3)) * para.page_size *
662 (para.dual_rank ? 2 : 1);