blob: 2d12661a14d3677f45acfeb63e0146172595d61b [file] [log] [blame]
Jens Kuske53f018e2015-11-17 15:12:59 +01001/*
2 * sun8i H3 platform dram controller init
3 *
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>
9 *
10 * SPDX-License-Identifier: GPL-2.0+
11 */
12#include <common.h>
13#include <asm/io.h>
14#include <asm/arch/clock.h>
15#include <asm/arch/dram.h>
Jens Kuskef6138172017-01-02 11:48:42 +000016#include <asm/arch/cpu.h>
Jens Kuske53f018e2015-11-17 15:12:59 +010017#include <linux/kconfig.h>
18
Jens Kuske8bbadc82017-01-02 11:48:40 +000019/*
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.
24 */
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)
Jens Kuske53f018e2015-11-17 15:12:59 +010029struct dram_para {
Jens Kuske53f018e2015-11-17 15:12:59 +010030 u16 page_size;
31 u8 bus_width;
32 u8 dual_rank;
33 u8 row_bits;
Jens Kuske8bbadc82017-01-02 11:48:40 +000034 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];
Jens Kuske53f018e2015-11-17 15:12:59 +010037};
38
39static inline int ns_to_t(int nanoseconds)
40{
41 const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
42
43 return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
44}
45
Jens Kuske53f018e2015-11-17 15:12:59 +010046static void mctl_phy_init(u32 val)
47{
48 struct sunxi_mctl_ctl_reg * const mctl_ctl =
49 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
50
51 writel(val | PIR_INIT, &mctl_ctl->pir);
52 mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1);
53}
54
Jens Kuske8bbadc82017-01-02 11:48:40 +000055static void mctl_set_bit_delays(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +010056{
57 struct sunxi_mctl_ctl_reg * const mctl_ctl =
58 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
59 int i, j;
Jens Kuske53f018e2015-11-17 15:12:59 +010060
61 clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
62
Jens Kuske8bbadc82017-01-02 11:48:40 +000063 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]);
Jens Kuske53f018e2015-11-17 15:12:59 +010068
Jens Kuske8bbadc82017-01-02 11:48:40 +000069 for (i = 0; i < 31; i++)
70 writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
71 &mctl_ctl->acbdlr[i]);
Jens Kuske53f018e2015-11-17 15:12:59 +010072
Chen-Yu Tsai143ef792016-12-01 19:09:57 +080073#ifdef CONFIG_MACH_SUN8I_R40
74 /* DQSn, DMn, DQn output enable bit delay */
75 for (i = 0; i < 4; i++)
76 writel(0x6 << 24, &mctl_ctl->dx[i].sdlr);
77#endif
78
Jens Kuske53f018e2015-11-17 15:12:59 +010079 setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
Jens Kuske53f018e2015-11-17 15:12:59 +010080}
81
Philipp Tomsich3c31ba92017-01-02 11:48:38 +000082enum {
83 MBUS_PORT_CPU = 0,
84 MBUS_PORT_GPU = 1,
85 MBUS_PORT_UNUSED = 2,
86 MBUS_PORT_DMA = 3,
87 MBUS_PORT_VE = 4,
88 MBUS_PORT_CSI = 5,
89 MBUS_PORT_NAND = 6,
90 MBUS_PORT_SS = 7,
91 MBUS_PORT_TS = 8,
92 MBUS_PORT_DI = 9,
93 MBUS_PORT_DE = 10,
94 MBUS_PORT_DE_CFD = 11,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +080095 MBUS_PORT_UNKNOWN1 = 12,
96 MBUS_PORT_UNKNOWN2 = 13,
97 MBUS_PORT_UNKNOWN3 = 14,
Philipp Tomsich3c31ba92017-01-02 11:48:38 +000098};
99
100enum {
101 MBUS_QOS_LOWEST = 0,
102 MBUS_QOS_LOW,
103 MBUS_QOS_HIGH,
104 MBUS_QOS_HIGHEST
105};
106
107inline void mbus_configure_port(u8 port,
108 bool bwlimit,
109 bool priority,
110 u8 qos, /* MBUS_QOS_LOWEST .. MBUS_QOS_HIGEST */
111 u8 waittime, /* 0 .. 0xf */
112 u8 acs, /* 0 .. 0xff */
113 u16 bwl0, /* 0 .. 0xffff, bandwidth limit in MB/s */
114 u16 bwl1,
115 u16 bwl2)
116{
117 struct sunxi_mctl_com_reg * const mctl_com =
118 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
119
120 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
121 | (priority ? (1 << 1) : 0)
122 | ((qos & 0x3) << 2)
123 | ((waittime & 0xf) << 4)
124 | ((acs & 0xff) << 8)
125 | (bwl0 << 16) );
126 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
127
128 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
129 writel(cfg0, &mctl_com->mcr[port][0]);
130 writel(cfg1, &mctl_com->mcr[port][1]);
131}
132
133#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
134 mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
135 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
136
Jens Kuskef6138172017-01-02 11:48:42 +0000137static void mctl_set_master_priority_h3(void)
Jens Kuske53f018e2015-11-17 15:12:59 +0100138{
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 */
Jens Kuskef6138172017-01-02 11:48:42 +0000143 writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100144
145 /* set cpu high priority */
146 writel(0x00000001, &mctl_com->mapr);
147
Philipp Tomsich3c31ba92017-01-02 11:48:38 +0000148 MBUS_CONF( CPU, true, HIGHEST, 0, 512, 256, 128);
149 MBUS_CONF( GPU, true, HIGH, 0, 1536, 1024, 256);
150 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
151 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
152 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
153 MBUS_CONF( CSI, true, HIGHEST, 0, 256, 128, 32);
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, HIGHEST, 3, 8192, 6120, 1024);
159 MBUS_CONF(DE_CFD, true, HIGH, 0, 1024, 288, 64);
Jens Kuske53f018e2015-11-17 15:12:59 +0100160}
161
Jens Kuskef6138172017-01-02 11:48:42 +0000162static 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
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000189static 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
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800217static 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
Jens Kuskef6138172017-01-02 11:48:42 +0000253static 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_A64:
260 mctl_set_master_priority_a64();
261 return;
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000262 case SOCID_H5:
263 mctl_set_master_priority_h5();
264 return;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800265 case SOCID_R40:
266 mctl_set_master_priority_r40();
267 return;
Jens Kuskef6138172017-01-02 11:48:42 +0000268 }
269}
270
271static void mctl_set_timing_params(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100272{
273 struct sunxi_mctl_ctl_reg * const mctl_ctl =
274 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
275
276 u8 tccd = 2;
277 u8 tfaw = ns_to_t(50);
278 u8 trrd = max(ns_to_t(10), 4);
279 u8 trcd = ns_to_t(15);
280 u8 trc = ns_to_t(53);
281 u8 txp = max(ns_to_t(8), 3);
282 u8 twtr = max(ns_to_t(8), 4);
283 u8 trtp = max(ns_to_t(8), 4);
284 u8 twr = max(ns_to_t(15), 3);
285 u8 trp = ns_to_t(15);
286 u8 tras = ns_to_t(38);
287 u16 trefi = ns_to_t(7800) / 32;
288 u16 trfc = ns_to_t(350);
289
290 u8 tmrw = 0;
291 u8 tmrd = 4;
292 u8 tmod = 12;
293 u8 tcke = 3;
294 u8 tcksrx = 5;
295 u8 tcksre = 5;
296 u8 tckesr = 4;
297 u8 trasmax = 24;
298
299 u8 tcl = 6; /* CL 12 */
300 u8 tcwl = 4; /* CWL 8 */
301 u8 t_rdata_en = 4;
302 u8 wr_latency = 2;
303
304 u32 tdinit0 = (500 * CONFIG_DRAM_CLK) + 1; /* 500us */
305 u32 tdinit1 = (360 * CONFIG_DRAM_CLK) / 1000 + 1; /* 360ns */
306 u32 tdinit2 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */
307 u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */
308
309 u8 twtp = tcwl + 2 + twr; /* WL + BL / 2 + tWR */
310 u8 twr2rd = tcwl + 2 + twtr; /* WL + BL / 2 + tWTR */
311 u8 trd2wr = tcl + 2 + 1 - tcwl; /* RL + BL / 2 + 2 - WL */
312
313 /* set mode register */
314 writel(0x1c70, &mctl_ctl->mr[0]); /* CL=11, WR=12 */
315 writel(0x40, &mctl_ctl->mr[1]);
316 writel(0x18, &mctl_ctl->mr[2]); /* CWL=8 */
317 writel(0x0, &mctl_ctl->mr[3]);
318
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800319 if (socid == SOCID_R40)
320 writel(0x3, &mctl_ctl->lp3mr11); /* odt_en[7:4] */
321
Jens Kuske53f018e2015-11-17 15:12:59 +0100322 /* set DRAM timing */
323 writel(DRAMTMG0_TWTP(twtp) | DRAMTMG0_TFAW(tfaw) |
324 DRAMTMG0_TRAS_MAX(trasmax) | DRAMTMG0_TRAS(tras),
325 &mctl_ctl->dramtmg[0]);
326 writel(DRAMTMG1_TXP(txp) | DRAMTMG1_TRTP(trtp) | DRAMTMG1_TRC(trc),
327 &mctl_ctl->dramtmg[1]);
328 writel(DRAMTMG2_TCWL(tcwl) | DRAMTMG2_TCL(tcl) |
329 DRAMTMG2_TRD2WR(trd2wr) | DRAMTMG2_TWR2RD(twr2rd),
330 &mctl_ctl->dramtmg[2]);
331 writel(DRAMTMG3_TMRW(tmrw) | DRAMTMG3_TMRD(tmrd) | DRAMTMG3_TMOD(tmod),
332 &mctl_ctl->dramtmg[3]);
333 writel(DRAMTMG4_TRCD(trcd) | DRAMTMG4_TCCD(tccd) | DRAMTMG4_TRRD(trrd) |
334 DRAMTMG4_TRP(trp), &mctl_ctl->dramtmg[4]);
335 writel(DRAMTMG5_TCKSRX(tcksrx) | DRAMTMG5_TCKSRE(tcksre) |
336 DRAMTMG5_TCKESR(tckesr) | DRAMTMG5_TCKE(tcke),
337 &mctl_ctl->dramtmg[5]);
338
339 /* set two rank timing */
340 clrsetbits_le32(&mctl_ctl->dramtmg[8], (0xff << 8) | (0xff << 0),
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000341 ((socid == SOCID_H5 ? 0x33 : 0x66) << 8) | (0x10 << 0));
Jens Kuske53f018e2015-11-17 15:12:59 +0100342
343 /* set PHY interface timing, write latency and read latency configure */
344 writel((0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) |
345 (wr_latency << 0), &mctl_ctl->pitmg[0]);
346
347 /* set PHY timing, PTR0-2 use default */
348 writel(PTR3_TDINIT0(tdinit0) | PTR3_TDINIT1(tdinit1), &mctl_ctl->ptr[3]);
349 writel(PTR4_TDINIT2(tdinit2) | PTR4_TDINIT3(tdinit3), &mctl_ctl->ptr[4]);
350
351 /* set refresh timing */
352 writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg);
353}
354
Jens Kuskef6138172017-01-02 11:48:42 +0000355static u32 bin_to_mgray(int val)
356{
357 static const u8 lookup_table[32] = {
358 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
359 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
360 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
361 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
362 };
363
364 return lookup_table[clamp(val, 0, 31)];
365}
366
367static int mgray_to_bin(u32 val)
368{
369 static const u8 lookup_table[32] = {
370 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
371 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
372 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
373 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
374 };
375
376 return lookup_table[val & 0x1f];
377}
378
379static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100380{
381 struct sunxi_mctl_ctl_reg * const mctl_ctl =
382 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
383
Jens Kusked8b95932016-09-21 20:08:30 +0200384 if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
385 (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
386 u32 reg_val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100387
Jens Kusked8b95932016-09-21 20:08:30 +0200388 clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
389 CONFIG_DRAM_ZQ & 0xffff);
Jens Kuske53f018e2015-11-17 15:12:59 +0100390
391 writel(PIR_CLRSR, &mctl_ctl->pir);
392 mctl_phy_init(PIR_ZCAL);
393
Jens Kusked8b95932016-09-21 20:08:30 +0200394 reg_val = readl(&mctl_ctl->zqdr[0]);
395 reg_val &= (0x1f << 16) | (0x1f << 0);
396 reg_val |= reg_val << 8;
397 writel(reg_val, &mctl_ctl->zqdr[0]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100398
Jens Kusked8b95932016-09-21 20:08:30 +0200399 reg_val = readl(&mctl_ctl->zqdr[1]);
400 reg_val &= (0x1f << 16) | (0x1f << 0);
401 reg_val |= reg_val << 8;
402 writel(reg_val, &mctl_ctl->zqdr[1]);
403 writel(reg_val, &mctl_ctl->zqdr[2]);
404 } else {
405 int i;
406 u16 zq_val[6];
407 u8 val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100408
Jens Kusked8b95932016-09-21 20:08:30 +0200409 writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
410
411 for (i = 0; i < 6; i++) {
412 u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
Jens Kuske53f018e2015-11-17 15:12:59 +0100413
Jens Kusked8b95932016-09-21 20:08:30 +0200414 writel((zq << 20) | (zq << 16) | (zq << 12) |
415 (zq << 8) | (zq << 4) | (zq << 0),
416 &mctl_ctl->zqcr);
417
418 writel(PIR_CLRSR, &mctl_ctl->pir);
419 mctl_phy_init(PIR_ZCAL);
420
421 zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
422 writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
423
424 writel(PIR_CLRSR, &mctl_ctl->pir);
425 mctl_phy_init(PIR_ZCAL);
426
427 val = readl(&mctl_ctl->zqdr[0]) >> 24;
428 zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
429 }
430
431 writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
432 writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
433 writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
434 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100435}
436
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800437static void mctl_set_cr(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100438{
439 struct sunxi_mctl_com_reg * const mctl_com =
440 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
441
442 writel(MCTL_CR_BL8 | MCTL_CR_2T | MCTL_CR_DDR3 | MCTL_CR_INTERLEAVED |
443 MCTL_CR_EIGHT_BANKS | MCTL_CR_BUS_WIDTH(para->bus_width) |
444 (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
445 MCTL_CR_PAGE_SIZE(para->page_size) |
446 MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800447
448 if (socid == SOCID_R40) {
449 if (para->dual_rank)
450 panic("Dual rank memory not supported\n");
451
452 /* Mux pin to A15 address line for single rank memory. */
453 setbits_le32(&mctl_com->cr_r1, MCTL_CR_R1_MUX_A15);
454 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100455}
456
Jens Kuskef6138172017-01-02 11:48:42 +0000457static void mctl_sys_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100458{
459 struct sunxi_ccm_reg * const ccm =
460 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
461 struct sunxi_mctl_ctl_reg * const mctl_ctl =
462 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
463
464 clrbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
465 clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
466 clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
467 clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
468 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800469 if (socid == SOCID_A64 || socid == SOCID_R40)
Jens Kuskef6138172017-01-02 11:48:42 +0000470 clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
Jens Kuske53f018e2015-11-17 15:12:59 +0100471 udelay(10);
472
473 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
474 udelay(1000);
475
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800476 if (socid == SOCID_A64 || socid == SOCID_R40) {
Jens Kuskef6138172017-01-02 11:48:42 +0000477 clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
478 clrsetbits_le32(&ccm->dram_clk_cfg,
479 CCM_DRAMCLK_CFG_DIV_MASK |
480 CCM_DRAMCLK_CFG_SRC_MASK,
481 CCM_DRAMCLK_CFG_DIV(1) |
482 CCM_DRAMCLK_CFG_SRC_PLL11 |
483 CCM_DRAMCLK_CFG_UPD);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000484 } else if (socid == SOCID_H3 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000485 clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
486 clrsetbits_le32(&ccm->dram_clk_cfg,
487 CCM_DRAMCLK_CFG_DIV_MASK |
488 CCM_DRAMCLK_CFG_SRC_MASK,
489 CCM_DRAMCLK_CFG_DIV(1) |
490 CCM_DRAMCLK_CFG_SRC_PLL5 |
491 CCM_DRAMCLK_CFG_UPD);
492 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100493 mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
494
495 setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
496 setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
497 setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
498 setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
499
500 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
501 udelay(10);
502
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000503 writel(socid == SOCID_H5 ? 0x8000 : 0xc00e, &mctl_ctl->clken);
Jens Kuske53f018e2015-11-17 15:12:59 +0100504 udelay(500);
505}
506
Andre Przywarac98f5cc2017-01-02 11:48:43 +0000507/* These are more guessed based on some Allwinner code. */
508#define DX_GCR_ODT_DYNAMIC (0x0 << 4)
509#define DX_GCR_ODT_ALWAYS_ON (0x1 << 4)
510#define DX_GCR_ODT_OFF (0x2 << 4)
511
Jens Kuskef6138172017-01-02 11:48:42 +0000512static int mctl_channel_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100513{
514 struct sunxi_mctl_com_reg * const mctl_com =
515 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
516 struct sunxi_mctl_ctl_reg * const mctl_ctl =
517 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
518
519 unsigned int i;
520
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800521 mctl_set_cr(socid, para);
Jens Kuskef6138172017-01-02 11:48:42 +0000522 mctl_set_timing_params(socid, para);
523 mctl_set_master_priority(socid);
Jens Kuske53f018e2015-11-17 15:12:59 +0100524
525 /* setting VTC, default disable all VT */
526 clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000527 if (socid == SOCID_H5)
528 setbits_le32(&mctl_ctl->pgcr[1], (1 << 24) | (1 << 26));
529 else
530 clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26);
Jens Kuske53f018e2015-11-17 15:12:59 +0100531
532 /* increase DFI_PHY_UPD clock */
533 writel(PROTECT_MAGIC, &mctl_com->protect);
534 udelay(100);
535 clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16);
536 writel(0x0, &mctl_com->protect);
537 udelay(100);
538
539 /* set dramc odt */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000540 for (i = 0; i < 4; i++) {
541 u32 clearmask = (0x3 << 4) | (0x1 << 1) | (0x3 << 2) |
542 (0x3 << 12) | (0x3 << 14);
543 u32 setmask = IS_ENABLED(CONFIG_DRAM_ODT_EN) ?
544 DX_GCR_ODT_DYNAMIC : DX_GCR_ODT_OFF;
545
546 if (socid == SOCID_H5) {
547 clearmask |= 0x2 << 8;
548 setmask |= 0x4 << 8;
549 }
550 clrsetbits_le32(&mctl_ctl->dx[i].gcr, clearmask, setmask);
551 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100552
553 /* AC PDR should always ON */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000554 clrsetbits_le32(&mctl_ctl->aciocr, socid == SOCID_H5 ? (0x1 << 11) : 0,
555 0x1 << 1);
Jens Kuske53f018e2015-11-17 15:12:59 +0100556
557 /* set DQS auto gating PD mode */
558 setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
559
Jens Kuskef6138172017-01-02 11:48:42 +0000560 if (socid == SOCID_H3) {
561 /* dx ddr_clk & hdr_clk dynamic mode */
562 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
Jens Kuske53f018e2015-11-17 15:12:59 +0100563
Jens Kuskef6138172017-01-02 11:48:42 +0000564 /* dphy & aphy phase select 270 degree */
565 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
566 (0x1 << 10) | (0x2 << 8));
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000567 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000568 /* dphy & aphy phase select ? */
569 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
570 (0x0 << 10) | (0x3 << 8));
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800571 } else if (socid == SOCID_R40) {
572 /* dx ddr_clk & hdr_clk dynamic mode (tpr13[9] == 0) */
573 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
574
575 /* dphy & aphy phase select ? */
576 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
577 (0x0 << 10) | (0x3 << 8));
Jens Kuskef6138172017-01-02 11:48:42 +0000578 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100579
580 /* set half DQ */
581 if (para->bus_width != 32) {
Jens Kuske3e797582017-01-02 11:48:39 +0000582 writel(0x0, &mctl_ctl->dx[2].gcr);
583 writel(0x0, &mctl_ctl->dx[3].gcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100584 }
585
586 /* data training configuration */
587 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24,
588 (para->dual_rank ? 0x3 : 0x1) << 24);
589
Jens Kuske8bbadc82017-01-02 11:48:40 +0000590 mctl_set_bit_delays(para);
591 udelay(50);
Jens Kuske53f018e2015-11-17 15:12:59 +0100592
Jens Kuskef6138172017-01-02 11:48:42 +0000593 if (socid == SOCID_H3) {
594 mctl_h3_zq_calibration_quirk(para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100595
Jens Kuskef6138172017-01-02 11:48:42 +0000596 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
597 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000598 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
Jens Kuskef6138172017-01-02 11:48:42 +0000599 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
600
601 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
602 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000603 /* no PIR_QSGATE for H5 ???? */
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800604 } else if (socid == SOCID_R40) {
605 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
606
607 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
608 PIR_DRAMRST | PIR_DRAMINIT);
Jens Kuskef6138172017-01-02 11:48:42 +0000609 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100610
611 /* detect ranks and bus width */
612 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
613 /* only one rank */
Jens Kuske3e797582017-01-02 11:48:39 +0000614 if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2) ||
615 ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)) {
Jens Kuske53f018e2015-11-17 15:12:59 +0100616 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
617 para->dual_rank = 0;
618 }
619
620 /* only half DQ width */
Jens Kuske3e797582017-01-02 11:48:39 +0000621 if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) ||
622 ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) {
623 writel(0x0, &mctl_ctl->dx[2].gcr);
624 writel(0x0, &mctl_ctl->dx[3].gcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100625 para->bus_width = 16;
626 }
627
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800628 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100629 udelay(20);
630
631 /* re-train */
632 mctl_phy_init(PIR_QSGATE);
633 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
634 return 1;
635 }
636
637 /* check the dramc status */
638 mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
639
640 /* liuke added for refresh debug */
641 setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
642 udelay(10);
643 clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
644 udelay(10);
645
646 /* set PGCR3, CKE polarity */
Jens Kuskef6138172017-01-02 11:48:42 +0000647 if (socid == SOCID_H3)
648 writel(0x00aa0060, &mctl_ctl->pgcr[3]);
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800649 else if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40)
Jens Kuskef6138172017-01-02 11:48:42 +0000650 writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100651
652 /* power down zq calibration module for power save */
653 setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
654
655 /* enable master access */
656 writel(0xffffffff, &mctl_com->maer);
657
658 return 0;
659}
660
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800661static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100662{
663 /* detect row address bits */
664 para->page_size = 512;
665 para->row_bits = 16;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800666 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100667
668 for (para->row_bits = 11; para->row_bits < 16; para->row_bits++)
669 if (mctl_mem_matches((1 << (para->row_bits + 3)) * para->page_size))
670 break;
671
672 /* detect page size */
673 para->page_size = 8192;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800674 mctl_set_cr(socid, para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100675
676 for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2)
677 if (mctl_mem_matches(para->page_size))
678 break;
679}
680
Jens Kuske8bbadc82017-01-02 11:48:40 +0000681/*
682 * The actual values used here are taken from Allwinner provided boot0
683 * binaries, though they are probably board specific, so would likely benefit
684 * from invidual tuning for each board. Apparently a lot of boards copy from
685 * some Allwinner reference design, so we go with those generic values for now
686 * in the hope that they are reasonable for most (all?) boards.
687 */
688#define SUN8I_H3_DX_READ_DELAYS \
689 {{ 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
690 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
691 { 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
692 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }}
693#define SUN8I_H3_DX_WRITE_DELAYS \
694 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
695 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
696 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
697 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 }}
698#define SUN8I_H3_AC_DELAYS \
699 { 0, 0, 0, 0, 0, 0, 0, 0, \
700 0, 0, 0, 0, 0, 0, 0, 0, \
701 0, 0, 0, 0, 0, 0, 0, 0, \
702 0, 0, 0, 0, 0, 0, 0 }
703
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800704#define SUN8I_R40_DX_READ_DELAYS \
705 {{ 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
706 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
707 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
708 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 } }
709#define SUN8I_R40_DX_WRITE_DELAYS \
710 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
711 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
712 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 }, \
713 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 } }
714#define SUN8I_R40_AC_DELAYS \
715 { 0, 0, 3, 0, 0, 0, 0, 0, \
716 0, 0, 0, 0, 0, 0, 0, 0, \
717 0, 0, 0, 0, 0, 0, 0, 0, \
718 0, 0, 0, 0, 0, 0, 0 }
719
Jens Kuskef6138172017-01-02 11:48:42 +0000720#define SUN50I_A64_DX_READ_DELAYS \
721 {{ 16, 16, 16, 16, 17, 16, 16, 17, 16, 1, 0 }, \
722 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }, \
723 { 16, 17, 17, 16, 16, 16, 16, 16, 16, 0, 0 }, \
724 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }}
725#define SUN50I_A64_DX_WRITE_DELAYS \
726 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15 }, \
727 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 10, 10 }, \
728 { 1, 0, 1, 1, 1, 1, 1, 1, 0, 11, 11 }, \
729 { 1, 0, 0, 1, 1, 1, 1, 1, 0, 12, 12 }}
730#define SUN50I_A64_AC_DELAYS \
731 { 5, 5, 13, 10, 2, 5, 3, 3, \
732 0, 3, 3, 3, 1, 0, 0, 0, \
733 3, 4, 0, 3, 4, 1, 4, 0, \
734 1, 1, 0, 1, 13, 5, 4 }
735
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000736#define SUN8I_H5_DX_READ_DELAYS \
737 {{ 14, 15, 17, 17, 17, 17, 17, 18, 17, 3, 3 }, \
738 { 21, 21, 12, 22, 21, 21, 21, 21, 21, 3, 3 }, \
739 { 16, 19, 19, 17, 22, 22, 21, 22, 19, 3, 3 }, \
740 { 21, 21, 22, 22, 20, 21, 19, 19, 19, 3, 3 } }
741#define SUN8I_H5_DX_WRITE_DELAYS \
742 {{ 1, 2, 3, 4, 3, 4, 4, 4, 6, 6, 6 }, \
743 { 6, 6, 6, 5, 5, 5, 5, 5, 6, 6, 6 }, \
744 { 0, 2, 4, 2, 6, 5, 5, 5, 6, 6, 6 }, \
745 { 3, 3, 3, 2, 2, 1, 1, 1, 4, 4, 4 } }
746#define SUN8I_H5_AC_DELAYS \
747 { 0, 0, 5, 5, 0, 0, 0, 0, \
748 0, 0, 0, 0, 3, 3, 3, 3, \
749 3, 3, 3, 3, 3, 3, 3, 3, \
750 3, 3, 3, 3, 2, 0, 0 }
751
Jens Kuske53f018e2015-11-17 15:12:59 +0100752unsigned long sunxi_dram_init(void)
753{
754 struct sunxi_mctl_com_reg * const mctl_com =
755 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
756 struct sunxi_mctl_ctl_reg * const mctl_ctl =
757 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
758
759 struct dram_para para = {
Jens Kuske53f018e2015-11-17 15:12:59 +0100760 .dual_rank = 0,
761 .bus_width = 32,
762 .row_bits = 15,
763 .page_size = 4096,
Jens Kuskef6138172017-01-02 11:48:42 +0000764
765#if defined(CONFIG_MACH_SUN8I_H3)
Jens Kuske8bbadc82017-01-02 11:48:40 +0000766 .dx_read_delays = SUN8I_H3_DX_READ_DELAYS,
767 .dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS,
768 .ac_delays = SUN8I_H3_AC_DELAYS,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800769#elif defined(CONFIG_MACH_SUN8I_R40)
770 .dx_read_delays = SUN8I_R40_DX_READ_DELAYS,
771 .dx_write_delays = SUN8I_R40_DX_WRITE_DELAYS,
772 .ac_delays = SUN8I_R40_AC_DELAYS,
Jens Kuskef6138172017-01-02 11:48:42 +0000773#elif defined(CONFIG_MACH_SUN50I)
774 .dx_read_delays = SUN50I_A64_DX_READ_DELAYS,
775 .dx_write_delays = SUN50I_A64_DX_WRITE_DELAYS,
776 .ac_delays = SUN50I_A64_AC_DELAYS,
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000777#elif defined(CONFIG_MACH_SUN50I_H5)
778 .dx_read_delays = SUN8I_H5_DX_READ_DELAYS,
779 .dx_write_delays = SUN8I_H5_DX_WRITE_DELAYS,
780 .ac_delays = SUN8I_H5_AC_DELAYS,
Jens Kuskef6138172017-01-02 11:48:42 +0000781#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100782 };
Jens Kuskef6138172017-01-02 11:48:42 +0000783/*
784 * Let the compiler optimize alternatives away by passing this value into
785 * the static functions. This saves us #ifdefs, but still keeps the binary
786 * small.
787 */
788#if defined(CONFIG_MACH_SUN8I_H3)
789 uint16_t socid = SOCID_H3;
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800790#elif defined(CONFIG_MACH_SUN8I_R40)
791 uint16_t socid = SOCID_R40;
Jens Kuskef6138172017-01-02 11:48:42 +0000792#elif defined(CONFIG_MACH_SUN50I)
793 uint16_t socid = SOCID_A64;
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000794#elif defined(CONFIG_MACH_SUN50I_H5)
795 uint16_t socid = SOCID_H5;
Jens Kuskef6138172017-01-02 11:48:42 +0000796#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100797
Jens Kuskef6138172017-01-02 11:48:42 +0000798 mctl_sys_init(socid, &para);
799 if (mctl_channel_init(socid, &para))
Jens Kuske53f018e2015-11-17 15:12:59 +0100800 return 0;
801
802 if (para.dual_rank)
803 writel(0x00000303, &mctl_ctl->odtmap);
804 else
805 writel(0x00000201, &mctl_ctl->odtmap);
806 udelay(1);
807
808 /* odt delay */
Jens Kuskef6138172017-01-02 11:48:42 +0000809 if (socid == SOCID_H3)
810 writel(0x0c000400, &mctl_ctl->odtcfg);
811
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800812 if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40) {
813 /* VTF enable (tpr13[8] == 1) */
Andre Przywara5d0d28f2017-02-16 01:20:26 +0000814 setbits_le32(&mctl_ctl->vtfcr,
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800815 (socid != SOCID_A64 ? 3 : 2) << 8);
816 /* DQ hold disable (tpr13[26] == 1) */
Jens Kuskef6138172017-01-02 11:48:42 +0000817 clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
818 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100819
820 /* clear credit value */
821 setbits_le32(&mctl_com->cccr, 1 << 31);
822 udelay(10);
823
Chen-Yu Tsai143ef792016-12-01 19:09:57 +0800824 mctl_auto_detect_dram_size(socid, &para);
825 mctl_set_cr(socid, &para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100826
Andre Przywarad414c382017-01-02 11:48:44 +0000827 return (1UL << (para.row_bits + 3)) * para.page_size *
Jens Kuske53f018e2015-11-17 15:12:59 +0100828 (para.dual_rank ? 2 : 1);
829}