blob: 85e7a1874e1bea206d5b39d676101547e21e8837 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Jens Kuske53f018e2015-11-17 15:12:59 +01002/*
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>
Jens Kuske53f018e2015-11-17 15:12:59 +010010 */
11#include <common.h>
12#include <asm/io.h>
13#include <asm/arch/clock.h>
14#include <asm/arch/dram.h>
Jens Kuskef6138172017-01-02 11:48:42 +000015#include <asm/arch/cpu.h>
Jens Kuske53f018e2015-11-17 15:12:59 +010016#include <linux/kconfig.h>
17
Jens Kuske53f018e2015-11-17 15:12:59 +010018static void mctl_phy_init(u32 val)
19{
20 struct sunxi_mctl_ctl_reg * const mctl_ctl =
21 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
22
23 writel(val | PIR_INIT, &mctl_ctl->pir);
24 mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1);
25}
26
Jens Kuske8bbadc82017-01-02 11:48:40 +000027static void mctl_set_bit_delays(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +010028{
29 struct sunxi_mctl_ctl_reg * const mctl_ctl =
30 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
31 int i, j;
Jens Kuske53f018e2015-11-17 15:12:59 +010032
33 clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
34
Jens Kuske8bbadc82017-01-02 11:48:40 +000035 for (i = 0; i < NR_OF_BYTE_LANES; i++)
36 for (j = 0; j < LINES_PER_BYTE_LANE; j++)
37 writel(DXBDLR_WRITE_DELAY(para->dx_write_delays[i][j]) |
38 DXBDLR_READ_DELAY(para->dx_read_delays[i][j]),
39 &mctl_ctl->dx[i].bdlr[j]);
Jens Kuske53f018e2015-11-17 15:12:59 +010040
Jens Kuske8bbadc82017-01-02 11:48:40 +000041 for (i = 0; i < 31; i++)
42 writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
43 &mctl_ctl->acbdlr[i]);
Jens Kuske53f018e2015-11-17 15:12:59 +010044
Chen-Yu Tsai143ef792016-12-01 19:09:57 +080045#ifdef CONFIG_MACH_SUN8I_R40
46 /* DQSn, DMn, DQn output enable bit delay */
47 for (i = 0; i < 4; i++)
48 writel(0x6 << 24, &mctl_ctl->dx[i].sdlr);
49#endif
50
Jens Kuske53f018e2015-11-17 15:12:59 +010051 setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
Jens Kuske53f018e2015-11-17 15:12:59 +010052}
53
Philipp Tomsich3c31ba92017-01-02 11:48:38 +000054enum {
55 MBUS_PORT_CPU = 0,
56 MBUS_PORT_GPU = 1,
57 MBUS_PORT_UNUSED = 2,
58 MBUS_PORT_DMA = 3,
59 MBUS_PORT_VE = 4,
60 MBUS_PORT_CSI = 5,
61 MBUS_PORT_NAND = 6,
62 MBUS_PORT_SS = 7,
63 MBUS_PORT_TS = 8,
64 MBUS_PORT_DI = 9,
65 MBUS_PORT_DE = 10,
66 MBUS_PORT_DE_CFD = 11,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +080067 MBUS_PORT_UNKNOWN1 = 12,
68 MBUS_PORT_UNKNOWN2 = 13,
69 MBUS_PORT_UNKNOWN3 = 14,
Philipp Tomsich3c31ba92017-01-02 11:48:38 +000070};
71
72enum {
73 MBUS_QOS_LOWEST = 0,
74 MBUS_QOS_LOW,
75 MBUS_QOS_HIGH,
76 MBUS_QOS_HIGHEST
77};
78
79inline void mbus_configure_port(u8 port,
80 bool bwlimit,
81 bool priority,
82 u8 qos, /* MBUS_QOS_LOWEST .. MBUS_QOS_HIGEST */
83 u8 waittime, /* 0 .. 0xf */
84 u8 acs, /* 0 .. 0xff */
85 u16 bwl0, /* 0 .. 0xffff, bandwidth limit in MB/s */
86 u16 bwl1,
87 u16 bwl2)
88{
89 struct sunxi_mctl_com_reg * const mctl_com =
90 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
91
92 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
93 | (priority ? (1 << 1) : 0)
94 | ((qos & 0x3) << 2)
95 | ((waittime & 0xf) << 4)
96 | ((acs & 0xff) << 8)
97 | (bwl0 << 16) );
98 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
99
100 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
101 writel(cfg0, &mctl_com->mcr[port][0]);
102 writel(cfg1, &mctl_com->mcr[port][1]);
103}
104
105#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
106 mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
107 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
108
Jens Kuskef6138172017-01-02 11:48:42 +0000109static void mctl_set_master_priority_h3(void)
Jens Kuske53f018e2015-11-17 15:12:59 +0100110{
111 struct sunxi_mctl_com_reg * const mctl_com =
112 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
113
114 /* enable bandwidth limit windows and set windows size 1us */
Jens Kuskef6138172017-01-02 11:48:42 +0000115 writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100116
117 /* set cpu high priority */
118 writel(0x00000001, &mctl_com->mapr);
119
Philipp Tomsich3c31ba92017-01-02 11:48:38 +0000120 MBUS_CONF( CPU, true, HIGHEST, 0, 512, 256, 128);
121 MBUS_CONF( GPU, true, HIGH, 0, 1536, 1024, 256);
122 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
123 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
124 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
125 MBUS_CONF( CSI, true, HIGHEST, 0, 256, 128, 32);
126 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
127 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
128 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
129 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
130 MBUS_CONF( DE, true, HIGHEST, 3, 8192, 6120, 1024);
131 MBUS_CONF(DE_CFD, true, HIGH, 0, 1024, 288, 64);
Jens Kuske53f018e2015-11-17 15:12:59 +0100132}
133
Jens Kuskef6138172017-01-02 11:48:42 +0000134static void mctl_set_master_priority_a64(void)
135{
136 struct sunxi_mctl_com_reg * const mctl_com =
137 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
138
139 /* enable bandwidth limit windows and set windows size 1us */
140 writel(399, &mctl_com->tmr);
141 writel((1 << 16), &mctl_com->bwcr);
142
143 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet they
144 * initialise it */
145 MBUS_CONF( CPU, true, HIGHEST, 0, 160, 100, 80);
146 MBUS_CONF( GPU, false, HIGH, 0, 1536, 1400, 256);
147 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
148 MBUS_CONF( DMA, true, HIGH, 0, 256, 80, 100);
149 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
150 MBUS_CONF( CSI, true, HIGH, 0, 256, 128, 0);
151 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
152 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
153 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
154 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
155 MBUS_CONF( DE, true, HIGH, 2, 8192, 6144, 2048);
156 MBUS_CONF(DE_CFD, true, HIGH, 0, 1280, 144, 64);
157
158 writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
159}
160
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000161static void mctl_set_master_priority_h5(void)
162{
163 struct sunxi_mctl_com_reg * const mctl_com =
164 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
165
166 /* enable bandwidth limit windows and set windows size 1us */
167 writel(399, &mctl_com->tmr);
168 writel((1 << 16), &mctl_com->bwcr);
169
170 /* set cpu high priority */
171 writel(0x00000001, &mctl_com->mapr);
172
173 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet
174 * they initialise it */
175 MBUS_CONF( CPU, true, HIGHEST, 0, 300, 260, 150);
176 MBUS_CONF( GPU, true, HIGHEST, 0, 600, 400, 200);
177 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
178 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
179 MBUS_CONF( VE, true, HIGHEST, 0, 1900, 1500, 1000);
180 MBUS_CONF( CSI, true, HIGHEST, 0, 150, 120, 100);
181 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
182 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
183 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
184 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
185 MBUS_CONF( DE, true, HIGHEST, 3, 3400, 2400, 1024);
186 MBUS_CONF(DE_CFD, true, HIGHEST, 0, 600, 400, 200);
187}
188
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800189static void mctl_set_master_priority_r40(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
214 /*
215 * The port names are probably wrong, but no correct sources
216 * are available.
217 */
218 MBUS_CONF( DE, true, HIGH, 0, 128, 48, 0);
219 MBUS_CONF( DE_CFD, true, HIGH, 0, 384, 256, 0);
220 MBUS_CONF(UNKNOWN1, true, HIGHEST, 0, 512, 384, 256);
221 MBUS_CONF(UNKNOWN2, true, HIGHEST, 2, 8192, 6144, 1024);
222 MBUS_CONF(UNKNOWN3, true, HIGH, 0, 1280, 144, 64);
223}
224
Jens Kuskef6138172017-01-02 11:48:42 +0000225static void mctl_set_master_priority(uint16_t socid)
226{
227 switch (socid) {
228 case SOCID_H3:
229 mctl_set_master_priority_h3();
230 return;
231 case SOCID_A64:
232 mctl_set_master_priority_a64();
233 return;
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000234 case SOCID_H5:
235 mctl_set_master_priority_h5();
236 return;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800237 case SOCID_R40:
238 mctl_set_master_priority_r40();
239 return;
Jens Kuskef6138172017-01-02 11:48:42 +0000240 }
241}
242
Jens Kuskef6138172017-01-02 11:48:42 +0000243static u32 bin_to_mgray(int val)
244{
245 static const u8 lookup_table[32] = {
246 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
247 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
248 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
249 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
250 };
251
252 return lookup_table[clamp(val, 0, 31)];
253}
254
255static int mgray_to_bin(u32 val)
256{
257 static const u8 lookup_table[32] = {
258 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
259 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
260 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
261 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
262 };
263
264 return lookup_table[val & 0x1f];
265}
266
267static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100268{
269 struct sunxi_mctl_ctl_reg * const mctl_ctl =
270 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Icenowy Zhengb2607512017-06-03 17:10:16 +0800271 int zq_count;
272
273#if defined CONFIG_SUNXI_DRAM_DW_16BIT
274 zq_count = 4;
275#else
276 zq_count = 6;
277#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100278
Jens Kusked8b95932016-09-21 20:08:30 +0200279 if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
280 (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
281 u32 reg_val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100282
Jens Kusked8b95932016-09-21 20:08:30 +0200283 clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
284 CONFIG_DRAM_ZQ & 0xffff);
Jens Kuske53f018e2015-11-17 15:12:59 +0100285
286 writel(PIR_CLRSR, &mctl_ctl->pir);
287 mctl_phy_init(PIR_ZCAL);
288
Jens Kusked8b95932016-09-21 20:08:30 +0200289 reg_val = readl(&mctl_ctl->zqdr[0]);
290 reg_val &= (0x1f << 16) | (0x1f << 0);
291 reg_val |= reg_val << 8;
292 writel(reg_val, &mctl_ctl->zqdr[0]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100293
Jens Kusked8b95932016-09-21 20:08:30 +0200294 reg_val = readl(&mctl_ctl->zqdr[1]);
295 reg_val &= (0x1f << 16) | (0x1f << 0);
296 reg_val |= reg_val << 8;
297 writel(reg_val, &mctl_ctl->zqdr[1]);
298 writel(reg_val, &mctl_ctl->zqdr[2]);
299 } else {
300 int i;
301 u16 zq_val[6];
302 u8 val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100303
Jens Kusked8b95932016-09-21 20:08:30 +0200304 writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
305
Icenowy Zhengb2607512017-06-03 17:10:16 +0800306 for (i = 0; i < zq_count; i++) {
Jens Kusked8b95932016-09-21 20:08:30 +0200307 u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
Jens Kuske53f018e2015-11-17 15:12:59 +0100308
Jens Kusked8b95932016-09-21 20:08:30 +0200309 writel((zq << 20) | (zq << 16) | (zq << 12) |
310 (zq << 8) | (zq << 4) | (zq << 0),
311 &mctl_ctl->zqcr);
312
313 writel(PIR_CLRSR, &mctl_ctl->pir);
314 mctl_phy_init(PIR_ZCAL);
315
316 zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
317 writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
318
319 writel(PIR_CLRSR, &mctl_ctl->pir);
320 mctl_phy_init(PIR_ZCAL);
321
322 val = readl(&mctl_ctl->zqdr[0]) >> 24;
323 zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
324 }
325
326 writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
327 writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
Icenowy Zhengb2607512017-06-03 17:10:16 +0800328 if (zq_count > 4)
329 writel((zq_val[5] << 16) | zq_val[4],
330 &mctl_ctl->zqdr[2]);
Jens Kusked8b95932016-09-21 20:08:30 +0200331 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100332}
333
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800334static void mctl_set_cr(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100335{
336 struct sunxi_mctl_com_reg * const mctl_com =
337 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
338
Icenowy Zhengf09b48e2017-06-03 17:10:18 +0800339 writel(MCTL_CR_BL8 | MCTL_CR_INTERLEAVED |
340#if defined CONFIG_SUNXI_DRAM_DDR3
341 MCTL_CR_DDR3 | MCTL_CR_2T |
Icenowy Zhenge270a582017-06-03 17:10:20 +0800342#elif defined CONFIG_SUNXI_DRAM_DDR2
343 MCTL_CR_DDR2 | MCTL_CR_2T |
Icenowy Zheng3c1b9f12017-06-03 17:10:23 +0800344#elif defined CONFIG_SUNXI_DRAM_LPDDR3
345 MCTL_CR_LPDDR3 | MCTL_CR_1T |
Icenowy Zhengf09b48e2017-06-03 17:10:18 +0800346#else
347#error Unsupported DRAM type!
348#endif
Icenowy Zheng20020352017-06-03 17:10:17 +0800349 (para->bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) |
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800350 MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) |
Jens Kuske53f018e2015-11-17 15:12:59 +0100351 (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
352 MCTL_CR_PAGE_SIZE(para->page_size) |
353 MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800354
355 if (socid == SOCID_R40) {
356 if (para->dual_rank)
357 panic("Dual rank memory not supported\n");
358
359 /* Mux pin to A15 address line for single rank memory. */
360 setbits_le32(&mctl_com->cr_r1, MCTL_CR_R1_MUX_A15);
361 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100362}
363
Jens Kuskef6138172017-01-02 11:48:42 +0000364static void mctl_sys_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100365{
366 struct sunxi_ccm_reg * const ccm =
367 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
368 struct sunxi_mctl_ctl_reg * const mctl_ctl =
369 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
370
371 clrbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
372 clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
373 clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
374 clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
375 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800376 if (socid == SOCID_A64 || socid == SOCID_R40)
Jens Kuskef6138172017-01-02 11:48:42 +0000377 clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
Jens Kuske53f018e2015-11-17 15:12:59 +0100378 udelay(10);
379
380 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
381 udelay(1000);
382
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800383 if (socid == SOCID_A64 || socid == SOCID_R40) {
Jens Kuskef6138172017-01-02 11:48:42 +0000384 clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
385 clrsetbits_le32(&ccm->dram_clk_cfg,
386 CCM_DRAMCLK_CFG_DIV_MASK |
387 CCM_DRAMCLK_CFG_SRC_MASK,
388 CCM_DRAMCLK_CFG_DIV(1) |
389 CCM_DRAMCLK_CFG_SRC_PLL11 |
390 CCM_DRAMCLK_CFG_UPD);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000391 } else if (socid == SOCID_H3 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000392 clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
393 clrsetbits_le32(&ccm->dram_clk_cfg,
394 CCM_DRAMCLK_CFG_DIV_MASK |
395 CCM_DRAMCLK_CFG_SRC_MASK,
396 CCM_DRAMCLK_CFG_DIV(1) |
397 CCM_DRAMCLK_CFG_SRC_PLL5 |
398 CCM_DRAMCLK_CFG_UPD);
399 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100400 mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
401
402 setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
403 setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
404 setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
405 setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
406
407 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
408 udelay(10);
409
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000410 writel(socid == SOCID_H5 ? 0x8000 : 0xc00e, &mctl_ctl->clken);
Jens Kuske53f018e2015-11-17 15:12:59 +0100411 udelay(500);
412}
413
Andre Przywarac98f5cc2017-01-02 11:48:43 +0000414/* These are more guessed based on some Allwinner code. */
415#define DX_GCR_ODT_DYNAMIC (0x0 << 4)
416#define DX_GCR_ODT_ALWAYS_ON (0x1 << 4)
417#define DX_GCR_ODT_OFF (0x2 << 4)
418
Jens Kuskef6138172017-01-02 11:48:42 +0000419static int mctl_channel_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100420{
421 struct sunxi_mctl_com_reg * const mctl_com =
422 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
423 struct sunxi_mctl_ctl_reg * const mctl_ctl =
424 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
425
426 unsigned int i;
427
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800428 mctl_set_cr(socid, para);
Jens Kuskef6138172017-01-02 11:48:42 +0000429 mctl_set_timing_params(socid, para);
430 mctl_set_master_priority(socid);
Jens Kuske53f018e2015-11-17 15:12:59 +0100431
432 /* setting VTC, default disable all VT */
433 clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000434 if (socid == SOCID_H5)
435 setbits_le32(&mctl_ctl->pgcr[1], (1 << 24) | (1 << 26));
436 else
437 clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26);
Jens Kuske53f018e2015-11-17 15:12:59 +0100438
439 /* increase DFI_PHY_UPD clock */
440 writel(PROTECT_MAGIC, &mctl_com->protect);
441 udelay(100);
442 clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16);
443 writel(0x0, &mctl_com->protect);
444 udelay(100);
445
446 /* set dramc odt */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000447 for (i = 0; i < 4; i++) {
448 u32 clearmask = (0x3 << 4) | (0x1 << 1) | (0x3 << 2) |
449 (0x3 << 12) | (0x3 << 14);
450 u32 setmask = IS_ENABLED(CONFIG_DRAM_ODT_EN) ?
451 DX_GCR_ODT_DYNAMIC : DX_GCR_ODT_OFF;
452
453 if (socid == SOCID_H5) {
454 clearmask |= 0x2 << 8;
455 setmask |= 0x4 << 8;
456 }
457 clrsetbits_le32(&mctl_ctl->dx[i].gcr, clearmask, setmask);
458 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100459
460 /* AC PDR should always ON */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000461 clrsetbits_le32(&mctl_ctl->aciocr, socid == SOCID_H5 ? (0x1 << 11) : 0,
462 0x1 << 1);
Jens Kuske53f018e2015-11-17 15:12:59 +0100463
464 /* set DQS auto gating PD mode */
465 setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
466
Jens Kuskef6138172017-01-02 11:48:42 +0000467 if (socid == SOCID_H3) {
468 /* dx ddr_clk & hdr_clk dynamic mode */
469 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
Jens Kuske53f018e2015-11-17 15:12:59 +0100470
Jens Kuskef6138172017-01-02 11:48:42 +0000471 /* dphy & aphy phase select 270 degree */
472 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
473 (0x1 << 10) | (0x2 << 8));
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000474 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000475 /* dphy & aphy phase select ? */
476 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
477 (0x0 << 10) | (0x3 << 8));
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800478 } else if (socid == SOCID_R40) {
479 /* dx ddr_clk & hdr_clk dynamic mode (tpr13[9] == 0) */
480 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
481
482 /* dphy & aphy phase select ? */
483 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
484 (0x0 << 10) | (0x3 << 8));
Jens Kuskef6138172017-01-02 11:48:42 +0000485 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100486
487 /* set half DQ */
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800488 if (!para->bus_full_width) {
Icenowy Zhengb2607512017-06-03 17:10:16 +0800489#if defined CONFIG_SUNXI_DRAM_DW_32BIT
Jens Kuske3e797582017-01-02 11:48:39 +0000490 writel(0x0, &mctl_ctl->dx[2].gcr);
491 writel(0x0, &mctl_ctl->dx[3].gcr);
Icenowy Zhengb2607512017-06-03 17:10:16 +0800492#elif defined CONFIG_SUNXI_DRAM_DW_16BIT
493 writel(0x0, &mctl_ctl->dx[1].gcr);
494#else
495#error Unsupported DRAM bus width!
496#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100497 }
498
499 /* data training configuration */
500 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24,
501 (para->dual_rank ? 0x3 : 0x1) << 24);
502
Jens Kuske8bbadc82017-01-02 11:48:40 +0000503 mctl_set_bit_delays(para);
504 udelay(50);
Jens Kuske53f018e2015-11-17 15:12:59 +0100505
Jens Kuskef6138172017-01-02 11:48:42 +0000506 if (socid == SOCID_H3) {
507 mctl_h3_zq_calibration_quirk(para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100508
Jens Kuskef6138172017-01-02 11:48:42 +0000509 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
510 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000511 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000512 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
513
514 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
515 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000516 /* no PIR_QSGATE for H5 ???? */
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800517 } else if (socid == SOCID_R40) {
518 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
519
520 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
521 PIR_DRAMRST | PIR_DRAMINIT);
Jens Kuskef6138172017-01-02 11:48:42 +0000522 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100523
524 /* detect ranks and bus width */
525 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
526 /* only one rank */
Icenowy Zhengb2607512017-06-03 17:10:16 +0800527 if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2)
528#if defined CONFIG_SUNXI_DRAM_DW_32BIT
529 || ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)
530#endif
531 ) {
Jens Kuske53f018e2015-11-17 15:12:59 +0100532 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
533 para->dual_rank = 0;
534 }
535
536 /* only half DQ width */
Icenowy Zhengb2607512017-06-03 17:10:16 +0800537#if defined CONFIG_SUNXI_DRAM_DW_32BIT
Jens Kuske3e797582017-01-02 11:48:39 +0000538 if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) ||
539 ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) {
540 writel(0x0, &mctl_ctl->dx[2].gcr);
541 writel(0x0, &mctl_ctl->dx[3].gcr);
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800542 para->bus_full_width = 0;
Jens Kuske53f018e2015-11-17 15:12:59 +0100543 }
Icenowy Zhengb2607512017-06-03 17:10:16 +0800544#elif defined CONFIG_SUNXI_DRAM_DW_16BIT
545 if ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x1) {
546 writel(0x0, &mctl_ctl->dx[1].gcr);
547 para->bus_full_width = 0;
548 }
549#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100550
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800551 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100552 udelay(20);
553
554 /* re-train */
555 mctl_phy_init(PIR_QSGATE);
556 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
557 return 1;
558 }
559
560 /* check the dramc status */
561 mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
562
563 /* liuke added for refresh debug */
564 setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
565 udelay(10);
566 clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
567 udelay(10);
568
569 /* set PGCR3, CKE polarity */
Jens Kuskef6138172017-01-02 11:48:42 +0000570 if (socid == SOCID_H3)
571 writel(0x00aa0060, &mctl_ctl->pgcr[3]);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800572 else if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40)
Jens Kuskef6138172017-01-02 11:48:42 +0000573 writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100574
575 /* power down zq calibration module for power save */
576 setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
577
578 /* enable master access */
579 writel(0xffffffff, &mctl_com->maer);
580
581 return 0;
582}
583
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800584static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100585{
586 /* detect row address bits */
587 para->page_size = 512;
588 para->row_bits = 16;
Icenowy Zheng20020352017-06-03 17:10:17 +0800589 para->bank_bits = 2;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800590 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100591
592 for (para->row_bits = 11; para->row_bits < 16; para->row_bits++)
Icenowy Zheng20020352017-06-03 17:10:17 +0800593 if (mctl_mem_matches((1 << (para->row_bits + para->bank_bits)) * para->page_size))
Jens Kuske53f018e2015-11-17 15:12:59 +0100594 break;
595
Icenowy Zheng20020352017-06-03 17:10:17 +0800596 /* detect bank address bits */
597 para->bank_bits = 3;
598 mctl_set_cr(socid, para);
599
600 for (para->bank_bits = 2; para->bank_bits < 3; para->bank_bits++)
601 if (mctl_mem_matches((1 << para->bank_bits) * para->page_size))
602 break;
603
Jens Kuske53f018e2015-11-17 15:12:59 +0100604 /* detect page size */
605 para->page_size = 8192;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800606 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100607
608 for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2)
609 if (mctl_mem_matches(para->page_size))
610 break;
611}
612
Jens Kuske8bbadc82017-01-02 11:48:40 +0000613/*
614 * The actual values used here are taken from Allwinner provided boot0
615 * binaries, though they are probably board specific, so would likely benefit
616 * from invidual tuning for each board. Apparently a lot of boards copy from
617 * some Allwinner reference design, so we go with those generic values for now
618 * in the hope that they are reasonable for most (all?) boards.
619 */
620#define SUN8I_H3_DX_READ_DELAYS \
621 {{ 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
622 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
623 { 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
624 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }}
625#define SUN8I_H3_DX_WRITE_DELAYS \
626 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
627 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
628 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
629 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 }}
630#define SUN8I_H3_AC_DELAYS \
631 { 0, 0, 0, 0, 0, 0, 0, 0, \
632 0, 0, 0, 0, 0, 0, 0, 0, \
633 0, 0, 0, 0, 0, 0, 0, 0, \
634 0, 0, 0, 0, 0, 0, 0 }
635
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800636#define SUN8I_R40_DX_READ_DELAYS \
637 {{ 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
638 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
639 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
640 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 } }
641#define SUN8I_R40_DX_WRITE_DELAYS \
642 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
643 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
644 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
645 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 } }
646#define SUN8I_R40_AC_DELAYS \
647 { 0, 0, 3, 0, 0, 0, 0, 0, \
648 0, 0, 0, 0, 0, 0, 0, 0, \
649 0, 0, 0, 0, 0, 0, 0, 0, \
650 0, 0, 0, 0, 0, 0, 0 }
651
Jens Kuskef6138172017-01-02 11:48:42 +0000652#define SUN50I_A64_DX_READ_DELAYS \
653 {{ 16, 16, 16, 16, 17, 16, 16, 17, 16, 1, 0 }, \
654 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }, \
655 { 16, 17, 17, 16, 16, 16, 16, 16, 16, 0, 0 }, \
656 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }}
657#define SUN50I_A64_DX_WRITE_DELAYS \
658 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15 }, \
659 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 10, 10 }, \
660 { 1, 0, 1, 1, 1, 1, 1, 1, 0, 11, 11 }, \
661 { 1, 0, 0, 1, 1, 1, 1, 1, 0, 12, 12 }}
662#define SUN50I_A64_AC_DELAYS \
663 { 5, 5, 13, 10, 2, 5, 3, 3, \
664 0, 3, 3, 3, 1, 0, 0, 0, \
665 3, 4, 0, 3, 4, 1, 4, 0, \
666 1, 1, 0, 1, 13, 5, 4 }
667
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000668#define SUN8I_H5_DX_READ_DELAYS \
669 {{ 14, 15, 17, 17, 17, 17, 17, 18, 17, 3, 3 }, \
670 { 21, 21, 12, 22, 21, 21, 21, 21, 21, 3, 3 }, \
671 { 16, 19, 19, 17, 22, 22, 21, 22, 19, 3, 3 }, \
672 { 21, 21, 22, 22, 20, 21, 19, 19, 19, 3, 3 } }
673#define SUN8I_H5_DX_WRITE_DELAYS \
674 {{ 1, 2, 3, 4, 3, 4, 4, 4, 6, 6, 6 }, \
675 { 6, 6, 6, 5, 5, 5, 5, 5, 6, 6, 6 }, \
676 { 0, 2, 4, 2, 6, 5, 5, 5, 6, 6, 6 }, \
677 { 3, 3, 3, 2, 2, 1, 1, 1, 4, 4, 4 } }
678#define SUN8I_H5_AC_DELAYS \
679 { 0, 0, 5, 5, 0, 0, 0, 0, \
680 0, 0, 0, 0, 3, 3, 3, 3, \
681 3, 3, 3, 3, 3, 3, 3, 3, \
682 3, 3, 3, 3, 2, 0, 0 }
683
Jens Kuske53f018e2015-11-17 15:12:59 +0100684unsigned long sunxi_dram_init(void)
685{
686 struct sunxi_mctl_com_reg * const mctl_com =
687 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
688 struct sunxi_mctl_ctl_reg * const mctl_ctl =
689 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
690
691 struct dram_para para = {
Icenowy Zheng88048772017-06-03 17:10:19 +0800692 .dual_rank = 1,
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800693 .bus_full_width = 1,
Jens Kuske53f018e2015-11-17 15:12:59 +0100694 .row_bits = 15,
Icenowy Zheng20020352017-06-03 17:10:17 +0800695 .bank_bits = 3,
Jens Kuske53f018e2015-11-17 15:12:59 +0100696 .page_size = 4096,
Jens Kuskef6138172017-01-02 11:48:42 +0000697
698#if defined(CONFIG_MACH_SUN8I_H3)
Jens Kuske8bbadc82017-01-02 11:48:40 +0000699 .dx_read_delays = SUN8I_H3_DX_READ_DELAYS,
700 .dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS,
701 .ac_delays = SUN8I_H3_AC_DELAYS,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800702#elif defined(CONFIG_MACH_SUN8I_R40)
703 .dx_read_delays = SUN8I_R40_DX_READ_DELAYS,
704 .dx_write_delays = SUN8I_R40_DX_WRITE_DELAYS,
705 .ac_delays = SUN8I_R40_AC_DELAYS,
Jens Kuskef6138172017-01-02 11:48:42 +0000706#elif defined(CONFIG_MACH_SUN50I)
707 .dx_read_delays = SUN50I_A64_DX_READ_DELAYS,
708 .dx_write_delays = SUN50I_A64_DX_WRITE_DELAYS,
709 .ac_delays = SUN50I_A64_AC_DELAYS,
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000710#elif defined(CONFIG_MACH_SUN50I_H5)
711 .dx_read_delays = SUN8I_H5_DX_READ_DELAYS,
712 .dx_write_delays = SUN8I_H5_DX_WRITE_DELAYS,
713 .ac_delays = SUN8I_H5_AC_DELAYS,
Jens Kuskef6138172017-01-02 11:48:42 +0000714#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100715 };
Jens Kuskef6138172017-01-02 11:48:42 +0000716/*
717 * Let the compiler optimize alternatives away by passing this value into
718 * the static functions. This saves us #ifdefs, but still keeps the binary
719 * small.
720 */
721#if defined(CONFIG_MACH_SUN8I_H3)
722 uint16_t socid = SOCID_H3;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800723#elif defined(CONFIG_MACH_SUN8I_R40)
724 uint16_t socid = SOCID_R40;
Icenowy Zheng88048772017-06-03 17:10:19 +0800725 /* Currently we cannot support R40 with dual rank memory */
726 para.dual_rank = 0;
Icenowy Zhengfe052172017-06-03 17:10:21 +0800727#elif defined(CONFIG_MACH_SUN8I_V3S)
728 /* TODO: set delays and mbus priority for V3s */
729 uint16_t socid = SOCID_H3;
Jens Kuskef6138172017-01-02 11:48:42 +0000730#elif defined(CONFIG_MACH_SUN50I)
731 uint16_t socid = SOCID_A64;
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000732#elif defined(CONFIG_MACH_SUN50I_H5)
733 uint16_t socid = SOCID_H5;
Jens Kuskef6138172017-01-02 11:48:42 +0000734#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100735
Jens Kuskef6138172017-01-02 11:48:42 +0000736 mctl_sys_init(socid, &para);
737 if (mctl_channel_init(socid, &para))
Jens Kuske53f018e2015-11-17 15:12:59 +0100738 return 0;
739
740 if (para.dual_rank)
741 writel(0x00000303, &mctl_ctl->odtmap);
742 else
743 writel(0x00000201, &mctl_ctl->odtmap);
744 udelay(1);
745
746 /* odt delay */
Jens Kuskef6138172017-01-02 11:48:42 +0000747 if (socid == SOCID_H3)
748 writel(0x0c000400, &mctl_ctl->odtcfg);
749
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800750 if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40) {
751 /* VTF enable (tpr13[8] == 1) */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000752 setbits_le32(&mctl_ctl->vtfcr,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800753 (socid != SOCID_A64 ? 3 : 2) << 8);
754 /* DQ hold disable (tpr13[26] == 1) */
Jens Kuskef6138172017-01-02 11:48:42 +0000755 clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
756 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100757
758 /* clear credit value */
759 setbits_le32(&mctl_com->cccr, 1 << 31);
760 udelay(10);
761
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800762 mctl_auto_detect_dram_size(socid, &para);
763 mctl_set_cr(socid, &para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100764
Icenowy Zheng20020352017-06-03 17:10:17 +0800765 return (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
766 (para.dual_rank ? 2 : 1);
Jens Kuske53f018e2015-11-17 15:12:59 +0100767}