blob: 5d84798ca4389d90ac8c1124e707fa2183cea626 [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>
Simon Glass97589732020-05-10 11:40:02 -060012#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Jens Kuske53f018e2015-11-17 15:12:59 +010014#include <asm/io.h>
15#include <asm/arch/clock.h>
16#include <asm/arch/dram.h>
Jens Kuskef6138172017-01-02 11:48:42 +000017#include <asm/arch/cpu.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Jens Kuske53f018e2015-11-17 15:12:59 +010019#include <linux/kconfig.h>
20
Jens Kuske53f018e2015-11-17 15:12:59 +010021static 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
Jens Kuske8bbadc82017-01-02 11:48:40 +000030static void mctl_set_bit_delays(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +010031{
32 struct sunxi_mctl_ctl_reg * const mctl_ctl =
33 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
34 int i, j;
Jens Kuske53f018e2015-11-17 15:12:59 +010035
36 clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
37
Jens Kuske8bbadc82017-01-02 11:48:40 +000038 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]);
Jens Kuske53f018e2015-11-17 15:12:59 +010043
Jens Kuske8bbadc82017-01-02 11:48:40 +000044 for (i = 0; i < 31; i++)
45 writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
46 &mctl_ctl->acbdlr[i]);
Jens Kuske53f018e2015-11-17 15:12:59 +010047
Chen-Yu Tsai143ef792016-12-01 19:09:57 +080048#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
Jens Kuske53f018e2015-11-17 15:12:59 +010054 setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
Jens Kuske53f018e2015-11-17 15:12:59 +010055}
56
Philipp Tomsich3c31ba92017-01-02 11:48:38 +000057enum {
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_TS = 8,
67 MBUS_PORT_DI = 9,
68 MBUS_PORT_DE = 10,
69 MBUS_PORT_DE_CFD = 11,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +080070 MBUS_PORT_UNKNOWN1 = 12,
71 MBUS_PORT_UNKNOWN2 = 13,
72 MBUS_PORT_UNKNOWN3 = 14,
Philipp Tomsich3c31ba92017-01-02 11:48:38 +000073};
74
75enum {
76 MBUS_QOS_LOWEST = 0,
77 MBUS_QOS_LOW,
78 MBUS_QOS_HIGH,
79 MBUS_QOS_HIGHEST
80};
81
82inline void mbus_configure_port(u8 port,
83 bool bwlimit,
84 bool priority,
85 u8 qos, /* MBUS_QOS_LOWEST .. MBUS_QOS_HIGEST */
86 u8 waittime, /* 0 .. 0xf */
87 u8 acs, /* 0 .. 0xff */
88 u16 bwl0, /* 0 .. 0xffff, bandwidth limit in MB/s */
89 u16 bwl1,
90 u16 bwl2)
91{
92 struct sunxi_mctl_com_reg * const mctl_com =
93 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
94
95 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
96 | (priority ? (1 << 1) : 0)
97 | ((qos & 0x3) << 2)
98 | ((waittime & 0xf) << 4)
99 | ((acs & 0xff) << 8)
100 | (bwl0 << 16) );
101 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
102
103 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
104 writel(cfg0, &mctl_com->mcr[port][0]);
105 writel(cfg1, &mctl_com->mcr[port][1]);
106}
107
108#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
109 mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
110 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
111
Jens Kuskef6138172017-01-02 11:48:42 +0000112static void mctl_set_master_priority_h3(void)
Jens Kuske53f018e2015-11-17 15:12:59 +0100113{
114 struct sunxi_mctl_com_reg * const mctl_com =
115 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
116
117 /* enable bandwidth limit windows and set windows size 1us */
Jens Kuskef6138172017-01-02 11:48:42 +0000118 writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100119
120 /* set cpu high priority */
121 writel(0x00000001, &mctl_com->mapr);
122
Philipp Tomsich3c31ba92017-01-02 11:48:38 +0000123 MBUS_CONF( CPU, true, HIGHEST, 0, 512, 256, 128);
124 MBUS_CONF( GPU, true, HIGH, 0, 1536, 1024, 256);
125 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
126 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
127 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
128 MBUS_CONF( CSI, true, HIGHEST, 0, 256, 128, 32);
129 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
130 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
131 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
132 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
133 MBUS_CONF( DE, true, HIGHEST, 3, 8192, 6120, 1024);
134 MBUS_CONF(DE_CFD, true, HIGH, 0, 1024, 288, 64);
Jens Kuske53f018e2015-11-17 15:12:59 +0100135}
136
Jens Kuskef6138172017-01-02 11:48:42 +0000137static void mctl_set_master_priority_a64(void)
138{
139 struct sunxi_mctl_com_reg * const mctl_com =
140 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
141
142 /* enable bandwidth limit windows and set windows size 1us */
143 writel(399, &mctl_com->tmr);
144 writel((1 << 16), &mctl_com->bwcr);
145
146 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet they
147 * initialise it */
148 MBUS_CONF( CPU, true, HIGHEST, 0, 160, 100, 80);
149 MBUS_CONF( GPU, false, HIGH, 0, 1536, 1400, 256);
150 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
151 MBUS_CONF( DMA, true, HIGH, 0, 256, 80, 100);
152 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
153 MBUS_CONF( CSI, true, HIGH, 0, 256, 128, 0);
154 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
155 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
156 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
157 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
158 MBUS_CONF( DE, true, HIGH, 2, 8192, 6144, 2048);
159 MBUS_CONF(DE_CFD, true, HIGH, 0, 1280, 144, 64);
160
161 writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
162}
163
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000164static void mctl_set_master_priority_h5(void)
165{
166 struct sunxi_mctl_com_reg * const mctl_com =
167 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
168
169 /* enable bandwidth limit windows and set windows size 1us */
170 writel(399, &mctl_com->tmr);
171 writel((1 << 16), &mctl_com->bwcr);
172
173 /* set cpu high priority */
174 writel(0x00000001, &mctl_com->mapr);
175
176 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet
177 * they initialise it */
178 MBUS_CONF( CPU, true, HIGHEST, 0, 300, 260, 150);
179 MBUS_CONF( GPU, true, HIGHEST, 0, 600, 400, 200);
180 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
181 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
182 MBUS_CONF( VE, true, HIGHEST, 0, 1900, 1500, 1000);
183 MBUS_CONF( CSI, true, HIGHEST, 0, 150, 120, 100);
184 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
185 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
186 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
187 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
188 MBUS_CONF( DE, true, HIGHEST, 3, 3400, 2400, 1024);
189 MBUS_CONF(DE_CFD, true, HIGHEST, 0, 600, 400, 200);
190}
191
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800192static void mctl_set_master_priority_r40(void)
193{
194 struct sunxi_mctl_com_reg * const mctl_com =
195 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
196
197 /* enable bandwidth limit windows and set windows size 1us */
198 writel(399, &mctl_com->tmr);
199 writel((1 << 16), &mctl_com->bwcr);
200
201 /* set cpu high priority */
202 writel(0x00000001, &mctl_com->mapr);
203
204 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet
205 * they initialise it */
206 MBUS_CONF( CPU, true, HIGHEST, 0, 300, 260, 150);
207 MBUS_CONF( GPU, true, HIGHEST, 0, 600, 400, 200);
208 MBUS_CONF( UNUSED, true, HIGHEST, 0, 512, 256, 96);
209 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
210 MBUS_CONF( VE, true, HIGHEST, 0, 1900, 1500, 1000);
211 MBUS_CONF( CSI, true, HIGHEST, 0, 150, 120, 100);
212 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
213 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
214 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
215 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
216
217 /*
218 * The port names are probably wrong, but no correct sources
219 * are available.
220 */
221 MBUS_CONF( DE, true, HIGH, 0, 128, 48, 0);
222 MBUS_CONF( DE_CFD, true, HIGH, 0, 384, 256, 0);
223 MBUS_CONF(UNKNOWN1, true, HIGHEST, 0, 512, 384, 256);
224 MBUS_CONF(UNKNOWN2, true, HIGHEST, 2, 8192, 6144, 1024);
225 MBUS_CONF(UNKNOWN3, true, HIGH, 0, 1280, 144, 64);
226}
227
Jens Kuskef6138172017-01-02 11:48:42 +0000228static void mctl_set_master_priority(uint16_t socid)
229{
230 switch (socid) {
231 case SOCID_H3:
232 mctl_set_master_priority_h3();
233 return;
234 case SOCID_A64:
235 mctl_set_master_priority_a64();
236 return;
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000237 case SOCID_H5:
238 mctl_set_master_priority_h5();
239 return;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800240 case SOCID_R40:
241 mctl_set_master_priority_r40();
242 return;
Jens Kuskef6138172017-01-02 11:48:42 +0000243 }
244}
245
Jens Kuskef6138172017-01-02 11:48:42 +0000246static u32 bin_to_mgray(int val)
247{
248 static const u8 lookup_table[32] = {
249 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
250 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
251 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
252 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
253 };
254
255 return lookup_table[clamp(val, 0, 31)];
256}
257
258static int mgray_to_bin(u32 val)
259{
260 static const u8 lookup_table[32] = {
261 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
262 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
263 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
264 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
265 };
266
267 return lookup_table[val & 0x1f];
268}
269
270static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100271{
272 struct sunxi_mctl_ctl_reg * const mctl_ctl =
273 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Icenowy Zhengb2607512017-06-03 17:10:16 +0800274 int zq_count;
275
276#if defined CONFIG_SUNXI_DRAM_DW_16BIT
277 zq_count = 4;
278#else
279 zq_count = 6;
280#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100281
Jens Kusked8b95932016-09-21 20:08:30 +0200282 if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
283 (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
284 u32 reg_val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100285
Jens Kusked8b95932016-09-21 20:08:30 +0200286 clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
287 CONFIG_DRAM_ZQ & 0xffff);
Jens Kuske53f018e2015-11-17 15:12:59 +0100288
289 writel(PIR_CLRSR, &mctl_ctl->pir);
290 mctl_phy_init(PIR_ZCAL);
291
Jens Kusked8b95932016-09-21 20:08:30 +0200292 reg_val = readl(&mctl_ctl->zqdr[0]);
293 reg_val &= (0x1f << 16) | (0x1f << 0);
294 reg_val |= reg_val << 8;
295 writel(reg_val, &mctl_ctl->zqdr[0]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100296
Jens Kusked8b95932016-09-21 20:08:30 +0200297 reg_val = readl(&mctl_ctl->zqdr[1]);
298 reg_val &= (0x1f << 16) | (0x1f << 0);
299 reg_val |= reg_val << 8;
300 writel(reg_val, &mctl_ctl->zqdr[1]);
301 writel(reg_val, &mctl_ctl->zqdr[2]);
302 } else {
303 int i;
304 u16 zq_val[6];
305 u8 val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100306
Jens Kusked8b95932016-09-21 20:08:30 +0200307 writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
308
Icenowy Zhengb2607512017-06-03 17:10:16 +0800309 for (i = 0; i < zq_count; i++) {
Jens Kusked8b95932016-09-21 20:08:30 +0200310 u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
Jens Kuske53f018e2015-11-17 15:12:59 +0100311
Jens Kusked8b95932016-09-21 20:08:30 +0200312 writel((zq << 20) | (zq << 16) | (zq << 12) |
313 (zq << 8) | (zq << 4) | (zq << 0),
314 &mctl_ctl->zqcr);
315
316 writel(PIR_CLRSR, &mctl_ctl->pir);
317 mctl_phy_init(PIR_ZCAL);
318
319 zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
320 writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
321
322 writel(PIR_CLRSR, &mctl_ctl->pir);
323 mctl_phy_init(PIR_ZCAL);
324
325 val = readl(&mctl_ctl->zqdr[0]) >> 24;
326 zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
327 }
328
329 writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
330 writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
Icenowy Zhengb2607512017-06-03 17:10:16 +0800331 if (zq_count > 4)
332 writel((zq_val[5] << 16) | zq_val[4],
333 &mctl_ctl->zqdr[2]);
Jens Kusked8b95932016-09-21 20:08:30 +0200334 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100335}
336
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800337static void mctl_set_cr(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100338{
339 struct sunxi_mctl_com_reg * const mctl_com =
340 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
341
Icenowy Zhengf09b48e2017-06-03 17:10:18 +0800342 writel(MCTL_CR_BL8 | MCTL_CR_INTERLEAVED |
343#if defined CONFIG_SUNXI_DRAM_DDR3
344 MCTL_CR_DDR3 | MCTL_CR_2T |
Icenowy Zhenge270a582017-06-03 17:10:20 +0800345#elif defined CONFIG_SUNXI_DRAM_DDR2
346 MCTL_CR_DDR2 | MCTL_CR_2T |
Icenowy Zheng3c1b9f12017-06-03 17:10:23 +0800347#elif defined CONFIG_SUNXI_DRAM_LPDDR3
348 MCTL_CR_LPDDR3 | MCTL_CR_1T |
Icenowy Zhengf09b48e2017-06-03 17:10:18 +0800349#else
350#error Unsupported DRAM type!
351#endif
Icenowy Zheng20020352017-06-03 17:10:17 +0800352 (para->bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) |
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800353 MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) |
Jens Kuske53f018e2015-11-17 15:12:59 +0100354 (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
355 MCTL_CR_PAGE_SIZE(para->page_size) |
356 MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800357
358 if (socid == SOCID_R40) {
359 if (para->dual_rank)
360 panic("Dual rank memory not supported\n");
361
362 /* Mux pin to A15 address line for single rank memory. */
363 setbits_le32(&mctl_com->cr_r1, MCTL_CR_R1_MUX_A15);
364 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100365}
366
Jens Kuskef6138172017-01-02 11:48:42 +0000367static void mctl_sys_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100368{
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;
373
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);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800379 if (socid == SOCID_A64 || socid == SOCID_R40)
Jens Kuskef6138172017-01-02 11:48:42 +0000380 clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
Jens Kuske53f018e2015-11-17 15:12:59 +0100381 udelay(10);
382
383 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
384 udelay(1000);
385
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800386 if (socid == SOCID_A64 || socid == SOCID_R40) {
Jens Kuskef6138172017-01-02 11:48:42 +0000387 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);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000394 } else if (socid == SOCID_H3 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000395 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);
402 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100403 mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
404
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);
409
410 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
411 udelay(10);
412
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000413 writel(socid == SOCID_H5 ? 0x8000 : 0xc00e, &mctl_ctl->clken);
Jens Kuske53f018e2015-11-17 15:12:59 +0100414 udelay(500);
415}
416
Andre Przywarac98f5cc2017-01-02 11:48:43 +0000417/* These are more guessed based on some Allwinner code. */
418#define DX_GCR_ODT_DYNAMIC (0x0 << 4)
419#define DX_GCR_ODT_ALWAYS_ON (0x1 << 4)
420#define DX_GCR_ODT_OFF (0x2 << 4)
421
Jens Kuskef6138172017-01-02 11:48:42 +0000422static int mctl_channel_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100423{
424 struct sunxi_mctl_com_reg * const mctl_com =
425 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
426 struct sunxi_mctl_ctl_reg * const mctl_ctl =
427 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
428
429 unsigned int i;
430
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800431 mctl_set_cr(socid, para);
Jens Kuskef6138172017-01-02 11:48:42 +0000432 mctl_set_timing_params(socid, para);
433 mctl_set_master_priority(socid);
Jens Kuske53f018e2015-11-17 15:12:59 +0100434
435 /* setting VTC, default disable all VT */
436 clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000437 if (socid == SOCID_H5)
438 setbits_le32(&mctl_ctl->pgcr[1], (1 << 24) | (1 << 26));
439 else
440 clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26);
Jens Kuske53f018e2015-11-17 15:12:59 +0100441
442 /* increase DFI_PHY_UPD clock */
443 writel(PROTECT_MAGIC, &mctl_com->protect);
444 udelay(100);
445 clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16);
446 writel(0x0, &mctl_com->protect);
447 udelay(100);
448
449 /* set dramc odt */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000450 for (i = 0; i < 4; i++) {
451 u32 clearmask = (0x3 << 4) | (0x1 << 1) | (0x3 << 2) |
452 (0x3 << 12) | (0x3 << 14);
453 u32 setmask = IS_ENABLED(CONFIG_DRAM_ODT_EN) ?
454 DX_GCR_ODT_DYNAMIC : DX_GCR_ODT_OFF;
455
456 if (socid == SOCID_H5) {
457 clearmask |= 0x2 << 8;
458 setmask |= 0x4 << 8;
459 }
460 clrsetbits_le32(&mctl_ctl->dx[i].gcr, clearmask, setmask);
461 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100462
463 /* AC PDR should always ON */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000464 clrsetbits_le32(&mctl_ctl->aciocr, socid == SOCID_H5 ? (0x1 << 11) : 0,
465 0x1 << 1);
Jens Kuske53f018e2015-11-17 15:12:59 +0100466
467 /* set DQS auto gating PD mode */
468 setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
469
Jens Kuskef6138172017-01-02 11:48:42 +0000470 if (socid == SOCID_H3) {
471 /* dx ddr_clk & hdr_clk dynamic mode */
472 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
Jens Kuske53f018e2015-11-17 15:12:59 +0100473
Jens Kuskef6138172017-01-02 11:48:42 +0000474 /* dphy & aphy phase select 270 degree */
475 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
476 (0x1 << 10) | (0x2 << 8));
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000477 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000478 /* dphy & aphy phase select ? */
479 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
480 (0x0 << 10) | (0x3 << 8));
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800481 } else if (socid == SOCID_R40) {
482 /* dx ddr_clk & hdr_clk dynamic mode (tpr13[9] == 0) */
483 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
484
485 /* dphy & aphy phase select ? */
486 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
487 (0x0 << 10) | (0x3 << 8));
Jens Kuskef6138172017-01-02 11:48:42 +0000488 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100489
490 /* set half DQ */
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800491 if (!para->bus_full_width) {
Icenowy Zhengb2607512017-06-03 17:10:16 +0800492#if defined CONFIG_SUNXI_DRAM_DW_32BIT
Jens Kuske3e797582017-01-02 11:48:39 +0000493 writel(0x0, &mctl_ctl->dx[2].gcr);
494 writel(0x0, &mctl_ctl->dx[3].gcr);
Icenowy Zhengb2607512017-06-03 17:10:16 +0800495#elif defined CONFIG_SUNXI_DRAM_DW_16BIT
496 writel(0x0, &mctl_ctl->dx[1].gcr);
497#else
498#error Unsupported DRAM bus width!
499#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100500 }
501
502 /* data training configuration */
503 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24,
504 (para->dual_rank ? 0x3 : 0x1) << 24);
505
Jens Kuske8bbadc82017-01-02 11:48:40 +0000506 mctl_set_bit_delays(para);
507 udelay(50);
Jens Kuske53f018e2015-11-17 15:12:59 +0100508
Jens Kuskef6138172017-01-02 11:48:42 +0000509 if (socid == SOCID_H3) {
510 mctl_h3_zq_calibration_quirk(para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100511
Jens Kuskef6138172017-01-02 11:48:42 +0000512 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
513 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000514 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000515 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
516
517 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
518 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000519 /* no PIR_QSGATE for H5 ???? */
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800520 } else if (socid == SOCID_R40) {
521 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
522
523 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
524 PIR_DRAMRST | PIR_DRAMINIT);
Jens Kuskef6138172017-01-02 11:48:42 +0000525 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100526
527 /* detect ranks and bus width */
528 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
529 /* only one rank */
Icenowy Zhengb2607512017-06-03 17:10:16 +0800530 if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2)
531#if defined CONFIG_SUNXI_DRAM_DW_32BIT
532 || ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)
533#endif
534 ) {
Jens Kuske53f018e2015-11-17 15:12:59 +0100535 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
536 para->dual_rank = 0;
537 }
538
539 /* only half DQ width */
Icenowy Zhengb2607512017-06-03 17:10:16 +0800540#if defined CONFIG_SUNXI_DRAM_DW_32BIT
Jens Kuske3e797582017-01-02 11:48:39 +0000541 if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) ||
542 ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) {
543 writel(0x0, &mctl_ctl->dx[2].gcr);
544 writel(0x0, &mctl_ctl->dx[3].gcr);
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800545 para->bus_full_width = 0;
Jens Kuske53f018e2015-11-17 15:12:59 +0100546 }
Icenowy Zhengb2607512017-06-03 17:10:16 +0800547#elif defined CONFIG_SUNXI_DRAM_DW_16BIT
548 if ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x1) {
549 writel(0x0, &mctl_ctl->dx[1].gcr);
550 para->bus_full_width = 0;
551 }
552#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100553
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800554 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100555 udelay(20);
556
557 /* re-train */
558 mctl_phy_init(PIR_QSGATE);
559 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
560 return 1;
561 }
562
563 /* check the dramc status */
564 mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
565
566 /* liuke added for refresh debug */
567 setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
568 udelay(10);
569 clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
570 udelay(10);
571
572 /* set PGCR3, CKE polarity */
Jens Kuskef6138172017-01-02 11:48:42 +0000573 if (socid == SOCID_H3)
574 writel(0x00aa0060, &mctl_ctl->pgcr[3]);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800575 else if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40)
Jens Kuskef6138172017-01-02 11:48:42 +0000576 writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100577
578 /* power down zq calibration module for power save */
579 setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
580
581 /* enable master access */
582 writel(0xffffffff, &mctl_com->maer);
583
584 return 0;
585}
586
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800587static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100588{
589 /* detect row address bits */
590 para->page_size = 512;
591 para->row_bits = 16;
Icenowy Zheng20020352017-06-03 17:10:17 +0800592 para->bank_bits = 2;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800593 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100594
595 for (para->row_bits = 11; para->row_bits < 16; para->row_bits++)
Icenowy Zheng20020352017-06-03 17:10:17 +0800596 if (mctl_mem_matches((1 << (para->row_bits + para->bank_bits)) * para->page_size))
Jens Kuske53f018e2015-11-17 15:12:59 +0100597 break;
598
Icenowy Zheng20020352017-06-03 17:10:17 +0800599 /* detect bank address bits */
600 para->bank_bits = 3;
601 mctl_set_cr(socid, para);
602
603 for (para->bank_bits = 2; para->bank_bits < 3; para->bank_bits++)
604 if (mctl_mem_matches((1 << para->bank_bits) * para->page_size))
605 break;
606
Jens Kuske53f018e2015-11-17 15:12:59 +0100607 /* detect page size */
608 para->page_size = 8192;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800609 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100610
611 for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2)
612 if (mctl_mem_matches(para->page_size))
613 break;
614}
615
Jens Kuske8bbadc82017-01-02 11:48:40 +0000616/*
617 * The actual values used here are taken from Allwinner provided boot0
618 * binaries, though they are probably board specific, so would likely benefit
619 * from invidual tuning for each board. Apparently a lot of boards copy from
620 * some Allwinner reference design, so we go with those generic values for now
621 * in the hope that they are reasonable for most (all?) boards.
622 */
623#define SUN8I_H3_DX_READ_DELAYS \
624 {{ 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
625 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
626 { 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
627 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }}
628#define SUN8I_H3_DX_WRITE_DELAYS \
629 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
630 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
631 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
632 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 }}
633#define SUN8I_H3_AC_DELAYS \
634 { 0, 0, 0, 0, 0, 0, 0, 0, \
635 0, 0, 0, 0, 0, 0, 0, 0, \
636 0, 0, 0, 0, 0, 0, 0, 0, \
637 0, 0, 0, 0, 0, 0, 0 }
638
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800639#define SUN8I_R40_DX_READ_DELAYS \
640 {{ 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
641 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
642 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
643 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 } }
644#define SUN8I_R40_DX_WRITE_DELAYS \
645 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
646 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
647 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
648 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 } }
649#define SUN8I_R40_AC_DELAYS \
650 { 0, 0, 3, 0, 0, 0, 0, 0, \
651 0, 0, 0, 0, 0, 0, 0, 0, \
652 0, 0, 0, 0, 0, 0, 0, 0, \
653 0, 0, 0, 0, 0, 0, 0 }
654
Jens Kuskef6138172017-01-02 11:48:42 +0000655#define SUN50I_A64_DX_READ_DELAYS \
656 {{ 16, 16, 16, 16, 17, 16, 16, 17, 16, 1, 0 }, \
657 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }, \
658 { 16, 17, 17, 16, 16, 16, 16, 16, 16, 0, 0 }, \
659 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }}
660#define SUN50I_A64_DX_WRITE_DELAYS \
661 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15 }, \
662 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 10, 10 }, \
663 { 1, 0, 1, 1, 1, 1, 1, 1, 0, 11, 11 }, \
664 { 1, 0, 0, 1, 1, 1, 1, 1, 0, 12, 12 }}
665#define SUN50I_A64_AC_DELAYS \
666 { 5, 5, 13, 10, 2, 5, 3, 3, \
667 0, 3, 3, 3, 1, 0, 0, 0, \
668 3, 4, 0, 3, 4, 1, 4, 0, \
669 1, 1, 0, 1, 13, 5, 4 }
670
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000671#define SUN8I_H5_DX_READ_DELAYS \
672 {{ 14, 15, 17, 17, 17, 17, 17, 18, 17, 3, 3 }, \
673 { 21, 21, 12, 22, 21, 21, 21, 21, 21, 3, 3 }, \
674 { 16, 19, 19, 17, 22, 22, 21, 22, 19, 3, 3 }, \
675 { 21, 21, 22, 22, 20, 21, 19, 19, 19, 3, 3 } }
676#define SUN8I_H5_DX_WRITE_DELAYS \
677 {{ 1, 2, 3, 4, 3, 4, 4, 4, 6, 6, 6 }, \
678 { 6, 6, 6, 5, 5, 5, 5, 5, 6, 6, 6 }, \
679 { 0, 2, 4, 2, 6, 5, 5, 5, 6, 6, 6 }, \
680 { 3, 3, 3, 2, 2, 1, 1, 1, 4, 4, 4 } }
681#define SUN8I_H5_AC_DELAYS \
682 { 0, 0, 5, 5, 0, 0, 0, 0, \
683 0, 0, 0, 0, 3, 3, 3, 3, \
684 3, 3, 3, 3, 3, 3, 3, 3, \
685 3, 3, 3, 3, 2, 0, 0 }
686
Jens Kuske53f018e2015-11-17 15:12:59 +0100687unsigned long sunxi_dram_init(void)
688{
689 struct sunxi_mctl_com_reg * const mctl_com =
690 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
691 struct sunxi_mctl_ctl_reg * const mctl_ctl =
692 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
693
694 struct dram_para para = {
Icenowy Zheng88048772017-06-03 17:10:19 +0800695 .dual_rank = 1,
Icenowy Zheng4323a8f2017-06-03 17:10:15 +0800696 .bus_full_width = 1,
Jens Kuske53f018e2015-11-17 15:12:59 +0100697 .row_bits = 15,
Icenowy Zheng20020352017-06-03 17:10:17 +0800698 .bank_bits = 3,
Jens Kuske53f018e2015-11-17 15:12:59 +0100699 .page_size = 4096,
Jens Kuskef6138172017-01-02 11:48:42 +0000700
701#if defined(CONFIG_MACH_SUN8I_H3)
Jens Kuske8bbadc82017-01-02 11:48:40 +0000702 .dx_read_delays = SUN8I_H3_DX_READ_DELAYS,
703 .dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS,
704 .ac_delays = SUN8I_H3_AC_DELAYS,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800705#elif defined(CONFIG_MACH_SUN8I_R40)
706 .dx_read_delays = SUN8I_R40_DX_READ_DELAYS,
707 .dx_write_delays = SUN8I_R40_DX_WRITE_DELAYS,
708 .ac_delays = SUN8I_R40_AC_DELAYS,
Jens Kuskef6138172017-01-02 11:48:42 +0000709#elif defined(CONFIG_MACH_SUN50I)
710 .dx_read_delays = SUN50I_A64_DX_READ_DELAYS,
711 .dx_write_delays = SUN50I_A64_DX_WRITE_DELAYS,
712 .ac_delays = SUN50I_A64_AC_DELAYS,
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000713#elif defined(CONFIG_MACH_SUN50I_H5)
714 .dx_read_delays = SUN8I_H5_DX_READ_DELAYS,
715 .dx_write_delays = SUN8I_H5_DX_WRITE_DELAYS,
716 .ac_delays = SUN8I_H5_AC_DELAYS,
Jens Kuskef6138172017-01-02 11:48:42 +0000717#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100718 };
Jens Kuskef6138172017-01-02 11:48:42 +0000719/*
720 * Let the compiler optimize alternatives away by passing this value into
721 * the static functions. This saves us #ifdefs, but still keeps the binary
722 * small.
723 */
724#if defined(CONFIG_MACH_SUN8I_H3)
725 uint16_t socid = SOCID_H3;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800726#elif defined(CONFIG_MACH_SUN8I_R40)
727 uint16_t socid = SOCID_R40;
Icenowy Zheng88048772017-06-03 17:10:19 +0800728 /* Currently we cannot support R40 with dual rank memory */
729 para.dual_rank = 0;
Icenowy Zhengfe052172017-06-03 17:10:21 +0800730#elif defined(CONFIG_MACH_SUN8I_V3S)
731 /* TODO: set delays and mbus priority for V3s */
732 uint16_t socid = SOCID_H3;
Jens Kuskef6138172017-01-02 11:48:42 +0000733#elif defined(CONFIG_MACH_SUN50I)
734 uint16_t socid = SOCID_A64;
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000735#elif defined(CONFIG_MACH_SUN50I_H5)
736 uint16_t socid = SOCID_H5;
Jens Kuskef6138172017-01-02 11:48:42 +0000737#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100738
Jens Kuskef6138172017-01-02 11:48:42 +0000739 mctl_sys_init(socid, &para);
740 if (mctl_channel_init(socid, &para))
Jens Kuske53f018e2015-11-17 15:12:59 +0100741 return 0;
742
743 if (para.dual_rank)
744 writel(0x00000303, &mctl_ctl->odtmap);
745 else
746 writel(0x00000201, &mctl_ctl->odtmap);
747 udelay(1);
748
749 /* odt delay */
Jens Kuskef6138172017-01-02 11:48:42 +0000750 if (socid == SOCID_H3)
751 writel(0x0c000400, &mctl_ctl->odtcfg);
752
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800753 if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40) {
754 /* VTF enable (tpr13[8] == 1) */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000755 setbits_le32(&mctl_ctl->vtfcr,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800756 (socid != SOCID_A64 ? 3 : 2) << 8);
757 /* DQ hold disable (tpr13[26] == 1) */
Jens Kuskef6138172017-01-02 11:48:42 +0000758 clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
759 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100760
761 /* clear credit value */
762 setbits_le32(&mctl_com->cccr, 1 << 31);
763 udelay(10);
764
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800765 mctl_auto_detect_dram_size(socid, &para);
766 mctl_set_cr(socid, &para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100767
Icenowy Zheng20020352017-06-03 17:10:17 +0800768 return (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
769 (para.dual_rank ? 2 : 1);
Jens Kuske53f018e2015-11-17 15:12:59 +0100770}