]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/arm/mach-sunxi/dram_sunxi_dw.c
Merge git://git.denx.de/u-boot-mmc
[people/ms/u-boot.git] / arch / arm / mach-sunxi / dram_sunxi_dw.c
CommitLineData
0404d53f
JK
1/*
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>
1bc464be 16#include <asm/arch/cpu.h>
0404d53f
JK
17#include <linux/kconfig.h>
18
0404d53f
JK
19static void mctl_phy_init(u32 val)
20{
21 struct sunxi_mctl_ctl_reg * const mctl_ctl =
22 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
23
24 writel(val | PIR_INIT, &mctl_ctl->pir);
25 mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1);
26}
27
e013bead 28static void mctl_set_bit_delays(struct dram_para *para)
0404d53f
JK
29{
30 struct sunxi_mctl_ctl_reg * const mctl_ctl =
31 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
32 int i, j;
0404d53f
JK
33
34 clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
35
e013bead
JK
36 for (i = 0; i < NR_OF_BYTE_LANES; i++)
37 for (j = 0; j < LINES_PER_BYTE_LANE; j++)
38 writel(DXBDLR_WRITE_DELAY(para->dx_write_delays[i][j]) |
39 DXBDLR_READ_DELAY(para->dx_read_delays[i][j]),
40 &mctl_ctl->dx[i].bdlr[j]);
0404d53f 41
e013bead
JK
42 for (i = 0; i < 31; i++)
43 writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
44 &mctl_ctl->acbdlr[i]);
0404d53f 45
8201188c
CYT
46#ifdef CONFIG_MACH_SUN8I_R40
47 /* DQSn, DMn, DQn output enable bit delay */
48 for (i = 0; i < 4; i++)
49 writel(0x6 << 24, &mctl_ctl->dx[i].sdlr);
50#endif
51
0404d53f 52 setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
0404d53f
JK
53}
54
dcb50090
PT
55enum {
56 MBUS_PORT_CPU = 0,
57 MBUS_PORT_GPU = 1,
58 MBUS_PORT_UNUSED = 2,
59 MBUS_PORT_DMA = 3,
60 MBUS_PORT_VE = 4,
61 MBUS_PORT_CSI = 5,
62 MBUS_PORT_NAND = 6,
63 MBUS_PORT_SS = 7,
64 MBUS_PORT_TS = 8,
65 MBUS_PORT_DI = 9,
66 MBUS_PORT_DE = 10,
67 MBUS_PORT_DE_CFD = 11,
8201188c
CYT
68 MBUS_PORT_UNKNOWN1 = 12,
69 MBUS_PORT_UNKNOWN2 = 13,
70 MBUS_PORT_UNKNOWN3 = 14,
dcb50090
PT
71};
72
73enum {
74 MBUS_QOS_LOWEST = 0,
75 MBUS_QOS_LOW,
76 MBUS_QOS_HIGH,
77 MBUS_QOS_HIGHEST
78};
79
80inline void mbus_configure_port(u8 port,
81 bool bwlimit,
82 bool priority,
83 u8 qos, /* MBUS_QOS_LOWEST .. MBUS_QOS_HIGEST */
84 u8 waittime, /* 0 .. 0xf */
85 u8 acs, /* 0 .. 0xff */
86 u16 bwl0, /* 0 .. 0xffff, bandwidth limit in MB/s */
87 u16 bwl1,
88 u16 bwl2)
89{
90 struct sunxi_mctl_com_reg * const mctl_com =
91 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
92
93 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
94 | (priority ? (1 << 1) : 0)
95 | ((qos & 0x3) << 2)
96 | ((waittime & 0xf) << 4)
97 | ((acs & 0xff) << 8)
98 | (bwl0 << 16) );
99 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
100
101 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
102 writel(cfg0, &mctl_com->mcr[port][0]);
103 writel(cfg1, &mctl_com->mcr[port][1]);
104}
105
106#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
107 mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
108 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
109
1bc464be 110static void mctl_set_master_priority_h3(void)
0404d53f
JK
111{
112 struct sunxi_mctl_com_reg * const mctl_com =
113 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
114
115 /* enable bandwidth limit windows and set windows size 1us */
1bc464be 116 writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
0404d53f
JK
117
118 /* set cpu high priority */
119 writel(0x00000001, &mctl_com->mapr);
120
dcb50090
PT
121 MBUS_CONF( CPU, true, HIGHEST, 0, 512, 256, 128);
122 MBUS_CONF( GPU, true, HIGH, 0, 1536, 1024, 256);
123 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
124 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
125 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
126 MBUS_CONF( CSI, true, HIGHEST, 0, 256, 128, 32);
127 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
128 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
129 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
130 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
131 MBUS_CONF( DE, true, HIGHEST, 3, 8192, 6120, 1024);
132 MBUS_CONF(DE_CFD, true, HIGH, 0, 1024, 288, 64);
0404d53f
JK
133}
134
1bc464be
JK
135static void mctl_set_master_priority_a64(void)
136{
137 struct sunxi_mctl_com_reg * const mctl_com =
138 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
139
140 /* enable bandwidth limit windows and set windows size 1us */
141 writel(399, &mctl_com->tmr);
142 writel((1 << 16), &mctl_com->bwcr);
143
144 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet they
145 * initialise it */
146 MBUS_CONF( CPU, true, HIGHEST, 0, 160, 100, 80);
147 MBUS_CONF( GPU, false, HIGH, 0, 1536, 1400, 256);
148 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
149 MBUS_CONF( DMA, true, HIGH, 0, 256, 80, 100);
150 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
151 MBUS_CONF( CSI, true, HIGH, 0, 256, 128, 0);
152 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
153 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
154 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
155 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
156 MBUS_CONF( DE, true, HIGH, 2, 8192, 6144, 2048);
157 MBUS_CONF(DE_CFD, true, HIGH, 0, 1280, 144, 64);
158
159 writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
160}
161
170817a4
AP
162static void mctl_set_master_priority_h5(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 /* set cpu high priority */
172 writel(0x00000001, &mctl_com->mapr);
173
174 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet
175 * they initialise it */
176 MBUS_CONF( CPU, true, HIGHEST, 0, 300, 260, 150);
177 MBUS_CONF( GPU, true, HIGHEST, 0, 600, 400, 200);
178 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
179 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
180 MBUS_CONF( VE, true, HIGHEST, 0, 1900, 1500, 1000);
181 MBUS_CONF( CSI, true, HIGHEST, 0, 150, 120, 100);
182 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
183 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
184 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
185 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
186 MBUS_CONF( DE, true, HIGHEST, 3, 3400, 2400, 1024);
187 MBUS_CONF(DE_CFD, true, HIGHEST, 0, 600, 400, 200);
188}
189
8201188c
CYT
190static void mctl_set_master_priority_r40(void)
191{
192 struct sunxi_mctl_com_reg * const mctl_com =
193 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
194
195 /* enable bandwidth limit windows and set windows size 1us */
196 writel(399, &mctl_com->tmr);
197 writel((1 << 16), &mctl_com->bwcr);
198
199 /* set cpu high priority */
200 writel(0x00000001, &mctl_com->mapr);
201
202 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet
203 * they initialise it */
204 MBUS_CONF( CPU, true, HIGHEST, 0, 300, 260, 150);
205 MBUS_CONF( GPU, true, HIGHEST, 0, 600, 400, 200);
206 MBUS_CONF( UNUSED, true, HIGHEST, 0, 512, 256, 96);
207 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
208 MBUS_CONF( VE, true, HIGHEST, 0, 1900, 1500, 1000);
209 MBUS_CONF( CSI, true, HIGHEST, 0, 150, 120, 100);
210 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
211 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
212 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
213 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
214
215 /*
216 * The port names are probably wrong, but no correct sources
217 * are available.
218 */
219 MBUS_CONF( DE, true, HIGH, 0, 128, 48, 0);
220 MBUS_CONF( DE_CFD, true, HIGH, 0, 384, 256, 0);
221 MBUS_CONF(UNKNOWN1, true, HIGHEST, 0, 512, 384, 256);
222 MBUS_CONF(UNKNOWN2, true, HIGHEST, 2, 8192, 6144, 1024);
223 MBUS_CONF(UNKNOWN3, true, HIGH, 0, 1280, 144, 64);
224}
225
1bc464be
JK
226static void mctl_set_master_priority(uint16_t socid)
227{
228 switch (socid) {
229 case SOCID_H3:
230 mctl_set_master_priority_h3();
231 return;
232 case SOCID_A64:
233 mctl_set_master_priority_a64();
234 return;
170817a4
AP
235 case SOCID_H5:
236 mctl_set_master_priority_h5();
237 return;
8201188c
CYT
238 case SOCID_R40:
239 mctl_set_master_priority_r40();
240 return;
1bc464be
JK
241 }
242}
243
1bc464be
JK
244static u32 bin_to_mgray(int val)
245{
246 static const u8 lookup_table[32] = {
247 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
248 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
249 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
250 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
251 };
252
253 return lookup_table[clamp(val, 0, 31)];
254}
255
256static int mgray_to_bin(u32 val)
257{
258 static const u8 lookup_table[32] = {
259 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
260 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
261 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
262 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
263 };
264
265 return lookup_table[val & 0x1f];
266}
267
268static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
0404d53f
JK
269{
270 struct sunxi_mctl_ctl_reg * const mctl_ctl =
271 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
87098d70
IZ
272 int zq_count;
273
274#if defined CONFIG_SUNXI_DRAM_DW_16BIT
275 zq_count = 4;
276#else
277 zq_count = 6;
278#endif
0404d53f 279
7c9454d4
JK
280 if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
281 (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
282 u32 reg_val;
0404d53f 283
7c9454d4
JK
284 clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
285 CONFIG_DRAM_ZQ & 0xffff);
0404d53f
JK
286
287 writel(PIR_CLRSR, &mctl_ctl->pir);
288 mctl_phy_init(PIR_ZCAL);
289
7c9454d4
JK
290 reg_val = readl(&mctl_ctl->zqdr[0]);
291 reg_val &= (0x1f << 16) | (0x1f << 0);
292 reg_val |= reg_val << 8;
293 writel(reg_val, &mctl_ctl->zqdr[0]);
0404d53f 294
7c9454d4
JK
295 reg_val = readl(&mctl_ctl->zqdr[1]);
296 reg_val &= (0x1f << 16) | (0x1f << 0);
297 reg_val |= reg_val << 8;
298 writel(reg_val, &mctl_ctl->zqdr[1]);
299 writel(reg_val, &mctl_ctl->zqdr[2]);
300 } else {
301 int i;
302 u16 zq_val[6];
303 u8 val;
0404d53f 304
7c9454d4
JK
305 writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
306
87098d70 307 for (i = 0; i < zq_count; i++) {
7c9454d4 308 u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
0404d53f 309
7c9454d4
JK
310 writel((zq << 20) | (zq << 16) | (zq << 12) |
311 (zq << 8) | (zq << 4) | (zq << 0),
312 &mctl_ctl->zqcr);
313
314 writel(PIR_CLRSR, &mctl_ctl->pir);
315 mctl_phy_init(PIR_ZCAL);
316
317 zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
318 writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
319
320 writel(PIR_CLRSR, &mctl_ctl->pir);
321 mctl_phy_init(PIR_ZCAL);
322
323 val = readl(&mctl_ctl->zqdr[0]) >> 24;
324 zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
325 }
326
327 writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
328 writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
87098d70
IZ
329 if (zq_count > 4)
330 writel((zq_val[5] << 16) | zq_val[4],
331 &mctl_ctl->zqdr[2]);
7c9454d4 332 }
0404d53f
JK
333}
334
8201188c 335static void mctl_set_cr(uint16_t socid, struct dram_para *para)
0404d53f
JK
336{
337 struct sunxi_mctl_com_reg * const mctl_com =
338 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
339
f6457ce5
IZ
340 writel(MCTL_CR_BL8 | MCTL_CR_INTERLEAVED |
341#if defined CONFIG_SUNXI_DRAM_DDR3
342 MCTL_CR_DDR3 | MCTL_CR_2T |
67337e68
IZ
343#elif defined CONFIG_SUNXI_DRAM_DDR2
344 MCTL_CR_DDR2 | MCTL_CR_2T |
72cc9870
IZ
345#elif defined CONFIG_SUNXI_DRAM_LPDDR3
346 MCTL_CR_LPDDR3 | MCTL_CR_1T |
f6457ce5
IZ
347#else
348#error Unsupported DRAM type!
349#endif
66b12526 350 (para->bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) |
f43a0099 351 MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) |
0404d53f
JK
352 (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
353 MCTL_CR_PAGE_SIZE(para->page_size) |
354 MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr);
8201188c
CYT
355
356 if (socid == SOCID_R40) {
357 if (para->dual_rank)
358 panic("Dual rank memory not supported\n");
359
360 /* Mux pin to A15 address line for single rank memory. */
361 setbits_le32(&mctl_com->cr_r1, MCTL_CR_R1_MUX_A15);
362 }
0404d53f
JK
363}
364
1bc464be 365static void mctl_sys_init(uint16_t socid, struct dram_para *para)
0404d53f
JK
366{
367 struct sunxi_ccm_reg * const ccm =
368 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
369 struct sunxi_mctl_ctl_reg * const mctl_ctl =
370 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
371
372 clrbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
373 clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
374 clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
375 clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
376 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
8201188c 377 if (socid == SOCID_A64 || socid == SOCID_R40)
1bc464be 378 clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
0404d53f
JK
379 udelay(10);
380
381 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
382 udelay(1000);
383
8201188c 384 if (socid == SOCID_A64 || socid == SOCID_R40) {
1bc464be
JK
385 clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
386 clrsetbits_le32(&ccm->dram_clk_cfg,
387 CCM_DRAMCLK_CFG_DIV_MASK |
388 CCM_DRAMCLK_CFG_SRC_MASK,
389 CCM_DRAMCLK_CFG_DIV(1) |
390 CCM_DRAMCLK_CFG_SRC_PLL11 |
391 CCM_DRAMCLK_CFG_UPD);
170817a4 392 } else if (socid == SOCID_H3 || socid == SOCID_H5) {
1bc464be
JK
393 clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
394 clrsetbits_le32(&ccm->dram_clk_cfg,
395 CCM_DRAMCLK_CFG_DIV_MASK |
396 CCM_DRAMCLK_CFG_SRC_MASK,
397 CCM_DRAMCLK_CFG_DIV(1) |
398 CCM_DRAMCLK_CFG_SRC_PLL5 |
399 CCM_DRAMCLK_CFG_UPD);
400 }
0404d53f
JK
401 mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
402
403 setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
404 setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
405 setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
406 setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
407
408 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
409 udelay(10);
410
170817a4 411 writel(socid == SOCID_H5 ? 0x8000 : 0xc00e, &mctl_ctl->clken);
0404d53f
JK
412 udelay(500);
413}
414
ed254862
AP
415/* These are more guessed based on some Allwinner code. */
416#define DX_GCR_ODT_DYNAMIC (0x0 << 4)
417#define DX_GCR_ODT_ALWAYS_ON (0x1 << 4)
418#define DX_GCR_ODT_OFF (0x2 << 4)
419
1bc464be 420static int mctl_channel_init(uint16_t socid, struct dram_para *para)
0404d53f
JK
421{
422 struct sunxi_mctl_com_reg * const mctl_com =
423 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
424 struct sunxi_mctl_ctl_reg * const mctl_ctl =
425 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
426
427 unsigned int i;
428
8201188c 429 mctl_set_cr(socid, para);
1bc464be
JK
430 mctl_set_timing_params(socid, para);
431 mctl_set_master_priority(socid);
0404d53f
JK
432
433 /* setting VTC, default disable all VT */
434 clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f);
170817a4
AP
435 if (socid == SOCID_H5)
436 setbits_le32(&mctl_ctl->pgcr[1], (1 << 24) | (1 << 26));
437 else
438 clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26);
0404d53f
JK
439
440 /* increase DFI_PHY_UPD clock */
441 writel(PROTECT_MAGIC, &mctl_com->protect);
442 udelay(100);
443 clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16);
444 writel(0x0, &mctl_com->protect);
445 udelay(100);
446
447 /* set dramc odt */
170817a4
AP
448 for (i = 0; i < 4; i++) {
449 u32 clearmask = (0x3 << 4) | (0x1 << 1) | (0x3 << 2) |
450 (0x3 << 12) | (0x3 << 14);
451 u32 setmask = IS_ENABLED(CONFIG_DRAM_ODT_EN) ?
452 DX_GCR_ODT_DYNAMIC : DX_GCR_ODT_OFF;
453
454 if (socid == SOCID_H5) {
455 clearmask |= 0x2 << 8;
456 setmask |= 0x4 << 8;
457 }
458 clrsetbits_le32(&mctl_ctl->dx[i].gcr, clearmask, setmask);
459 }
0404d53f
JK
460
461 /* AC PDR should always ON */
170817a4
AP
462 clrsetbits_le32(&mctl_ctl->aciocr, socid == SOCID_H5 ? (0x1 << 11) : 0,
463 0x1 << 1);
0404d53f
JK
464
465 /* set DQS auto gating PD mode */
466 setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
467
1bc464be
JK
468 if (socid == SOCID_H3) {
469 /* dx ddr_clk & hdr_clk dynamic mode */
470 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
471
472 /* dphy & aphy phase select 270 degree */
473 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
474 (0x1 << 10) | (0x2 << 8));
170817a4 475 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
8201188c
CYT
476 /* dphy & aphy phase select ? */
477 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
478 (0x0 << 10) | (0x3 << 8));
479 } else if (socid == SOCID_R40) {
480 /* dx ddr_clk & hdr_clk dynamic mode (tpr13[9] == 0) */
481 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
482
1bc464be
JK
483 /* dphy & aphy phase select ? */
484 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
485 (0x0 << 10) | (0x3 << 8));
486 }
0404d53f
JK
487
488 /* set half DQ */
f43a0099 489 if (!para->bus_full_width) {
87098d70 490#if defined CONFIG_SUNXI_DRAM_DW_32BIT
0eb6f9fd
JK
491 writel(0x0, &mctl_ctl->dx[2].gcr);
492 writel(0x0, &mctl_ctl->dx[3].gcr);
87098d70
IZ
493#elif defined CONFIG_SUNXI_DRAM_DW_16BIT
494 writel(0x0, &mctl_ctl->dx[1].gcr);
495#else
496#error Unsupported DRAM bus width!
497#endif
0404d53f
JK
498 }
499
500 /* data training configuration */
501 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24,
502 (para->dual_rank ? 0x3 : 0x1) << 24);
503
e013bead
JK
504 mctl_set_bit_delays(para);
505 udelay(50);
0404d53f 506
1bc464be
JK
507 if (socid == SOCID_H3) {
508 mctl_h3_zq_calibration_quirk(para);
0404d53f 509
1bc464be
JK
510 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
511 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
170817a4 512 } else if (socid == SOCID_A64 || socid == SOCID_H5) {
1bc464be
JK
513 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
514
515 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
516 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
170817a4 517 /* no PIR_QSGATE for H5 ???? */
8201188c
CYT
518 } else if (socid == SOCID_R40) {
519 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
520
521 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
522 PIR_DRAMRST | PIR_DRAMINIT);
1bc464be 523 }
0404d53f
JK
524
525 /* detect ranks and bus width */
526 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
527 /* only one rank */
87098d70
IZ
528 if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2)
529#if defined CONFIG_SUNXI_DRAM_DW_32BIT
530 || ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)
531#endif
532 ) {
0404d53f
JK
533 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
534 para->dual_rank = 0;
535 }
536
537 /* only half DQ width */
87098d70 538#if defined CONFIG_SUNXI_DRAM_DW_32BIT
0eb6f9fd
JK
539 if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) ||
540 ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) {
541 writel(0x0, &mctl_ctl->dx[2].gcr);
542 writel(0x0, &mctl_ctl->dx[3].gcr);
f43a0099 543 para->bus_full_width = 0;
0404d53f 544 }
87098d70
IZ
545#elif defined CONFIG_SUNXI_DRAM_DW_16BIT
546 if ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x1) {
547 writel(0x0, &mctl_ctl->dx[1].gcr);
548 para->bus_full_width = 0;
549 }
550#endif
0404d53f 551
8201188c 552 mctl_set_cr(socid, para);
0404d53f
JK
553 udelay(20);
554
555 /* re-train */
556 mctl_phy_init(PIR_QSGATE);
557 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
558 return 1;
559 }
560
561 /* check the dramc status */
562 mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
563
564 /* liuke added for refresh debug */
565 setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
566 udelay(10);
567 clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
568 udelay(10);
569
570 /* set PGCR3, CKE polarity */
1bc464be
JK
571 if (socid == SOCID_H3)
572 writel(0x00aa0060, &mctl_ctl->pgcr[3]);
8201188c 573 else if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40)
1bc464be 574 writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
0404d53f
JK
575
576 /* power down zq calibration module for power save */
577 setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
578
579 /* enable master access */
580 writel(0xffffffff, &mctl_com->maer);
581
582 return 0;
583}
584
8201188c 585static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para)
0404d53f
JK
586{
587 /* detect row address bits */
588 para->page_size = 512;
589 para->row_bits = 16;
66b12526 590 para->bank_bits = 2;
8201188c 591 mctl_set_cr(socid, para);
0404d53f
JK
592
593 for (para->row_bits = 11; para->row_bits < 16; para->row_bits++)
66b12526
IZ
594 if (mctl_mem_matches((1 << (para->row_bits + para->bank_bits)) * para->page_size))
595 break;
596
597 /* detect bank address bits */
598 para->bank_bits = 3;
599 mctl_set_cr(socid, para);
600
601 for (para->bank_bits = 2; para->bank_bits < 3; para->bank_bits++)
602 if (mctl_mem_matches((1 << para->bank_bits) * para->page_size))
0404d53f
JK
603 break;
604
605 /* detect page size */
606 para->page_size = 8192;
8201188c 607 mctl_set_cr(socid, para);
0404d53f
JK
608
609 for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2)
610 if (mctl_mem_matches(para->page_size))
611 break;
612}
613
e013bead
JK
614/*
615 * The actual values used here are taken from Allwinner provided boot0
616 * binaries, though they are probably board specific, so would likely benefit
617 * from invidual tuning for each board. Apparently a lot of boards copy from
618 * some Allwinner reference design, so we go with those generic values for now
619 * in the hope that they are reasonable for most (all?) boards.
620 */
621#define SUN8I_H3_DX_READ_DELAYS \
622 {{ 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
623 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
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#define SUN8I_H3_DX_WRITE_DELAYS \
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, 10, 10 }, \
630 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 }}
631#define SUN8I_H3_AC_DELAYS \
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, 0, \
635 0, 0, 0, 0, 0, 0, 0 }
636
8201188c
CYT
637#define SUN8I_R40_DX_READ_DELAYS \
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 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 } }
642#define SUN8I_R40_DX_WRITE_DELAYS \
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 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 } }
647#define SUN8I_R40_AC_DELAYS \
648 { 0, 0, 3, 0, 0, 0, 0, 0, \
649 0, 0, 0, 0, 0, 0, 0, 0, \
650 0, 0, 0, 0, 0, 0, 0, 0, \
651 0, 0, 0, 0, 0, 0, 0 }
652
1bc464be
JK
653#define SUN50I_A64_DX_READ_DELAYS \
654 {{ 16, 16, 16, 16, 17, 16, 16, 17, 16, 1, 0 }, \
655 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }, \
656 { 16, 17, 17, 16, 16, 16, 16, 16, 16, 0, 0 }, \
657 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }}
658#define SUN50I_A64_DX_WRITE_DELAYS \
659 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15 }, \
660 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 10, 10 }, \
661 { 1, 0, 1, 1, 1, 1, 1, 1, 0, 11, 11 }, \
662 { 1, 0, 0, 1, 1, 1, 1, 1, 0, 12, 12 }}
663#define SUN50I_A64_AC_DELAYS \
664 { 5, 5, 13, 10, 2, 5, 3, 3, \
665 0, 3, 3, 3, 1, 0, 0, 0, \
666 3, 4, 0, 3, 4, 1, 4, 0, \
667 1, 1, 0, 1, 13, 5, 4 }
668
170817a4
AP
669#define SUN8I_H5_DX_READ_DELAYS \
670 {{ 14, 15, 17, 17, 17, 17, 17, 18, 17, 3, 3 }, \
671 { 21, 21, 12, 22, 21, 21, 21, 21, 21, 3, 3 }, \
672 { 16, 19, 19, 17, 22, 22, 21, 22, 19, 3, 3 }, \
673 { 21, 21, 22, 22, 20, 21, 19, 19, 19, 3, 3 } }
674#define SUN8I_H5_DX_WRITE_DELAYS \
675 {{ 1, 2, 3, 4, 3, 4, 4, 4, 6, 6, 6 }, \
676 { 6, 6, 6, 5, 5, 5, 5, 5, 6, 6, 6 }, \
677 { 0, 2, 4, 2, 6, 5, 5, 5, 6, 6, 6 }, \
678 { 3, 3, 3, 2, 2, 1, 1, 1, 4, 4, 4 } }
679#define SUN8I_H5_AC_DELAYS \
680 { 0, 0, 5, 5, 0, 0, 0, 0, \
681 0, 0, 0, 0, 3, 3, 3, 3, \
682 3, 3, 3, 3, 3, 3, 3, 3, \
683 3, 3, 3, 3, 2, 0, 0 }
684
0404d53f
JK
685unsigned long sunxi_dram_init(void)
686{
687 struct sunxi_mctl_com_reg * const mctl_com =
688 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
689 struct sunxi_mctl_ctl_reg * const mctl_ctl =
690 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
691
692 struct dram_para para = {
176868bc 693 .dual_rank = 1,
f43a0099 694 .bus_full_width = 1,
0404d53f 695 .row_bits = 15,
66b12526 696 .bank_bits = 3,
0404d53f 697 .page_size = 4096,
1bc464be
JK
698
699#if defined(CONFIG_MACH_SUN8I_H3)
e013bead
JK
700 .dx_read_delays = SUN8I_H3_DX_READ_DELAYS,
701 .dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS,
702 .ac_delays = SUN8I_H3_AC_DELAYS,
8201188c
CYT
703#elif defined(CONFIG_MACH_SUN8I_R40)
704 .dx_read_delays = SUN8I_R40_DX_READ_DELAYS,
705 .dx_write_delays = SUN8I_R40_DX_WRITE_DELAYS,
706 .ac_delays = SUN8I_R40_AC_DELAYS,
1bc464be
JK
707#elif defined(CONFIG_MACH_SUN50I)
708 .dx_read_delays = SUN50I_A64_DX_READ_DELAYS,
709 .dx_write_delays = SUN50I_A64_DX_WRITE_DELAYS,
710 .ac_delays = SUN50I_A64_AC_DELAYS,
170817a4
AP
711#elif defined(CONFIG_MACH_SUN50I_H5)
712 .dx_read_delays = SUN8I_H5_DX_READ_DELAYS,
713 .dx_write_delays = SUN8I_H5_DX_WRITE_DELAYS,
714 .ac_delays = SUN8I_H5_AC_DELAYS,
1bc464be 715#endif
0404d53f 716 };
1bc464be
JK
717/*
718 * Let the compiler optimize alternatives away by passing this value into
719 * the static functions. This saves us #ifdefs, but still keeps the binary
720 * small.
721 */
722#if defined(CONFIG_MACH_SUN8I_H3)
723 uint16_t socid = SOCID_H3;
8201188c
CYT
724#elif defined(CONFIG_MACH_SUN8I_R40)
725 uint16_t socid = SOCID_R40;
176868bc
IZ
726 /* Currently we cannot support R40 with dual rank memory */
727 para.dual_rank = 0;
3ec0698b
IZ
728#elif defined(CONFIG_MACH_SUN8I_V3S)
729 /* TODO: set delays and mbus priority for V3s */
730 uint16_t socid = SOCID_H3;
1bc464be
JK
731#elif defined(CONFIG_MACH_SUN50I)
732 uint16_t socid = SOCID_A64;
170817a4
AP
733#elif defined(CONFIG_MACH_SUN50I_H5)
734 uint16_t socid = SOCID_H5;
1bc464be
JK
735#endif
736
737 mctl_sys_init(socid, &para);
738 if (mctl_channel_init(socid, &para))
0404d53f
JK
739 return 0;
740
741 if (para.dual_rank)
742 writel(0x00000303, &mctl_ctl->odtmap);
743 else
744 writel(0x00000201, &mctl_ctl->odtmap);
745 udelay(1);
746
747 /* odt delay */
1bc464be
JK
748 if (socid == SOCID_H3)
749 writel(0x0c000400, &mctl_ctl->odtcfg);
750
8201188c
CYT
751 if (socid == SOCID_A64 || socid == SOCID_H5 || socid == SOCID_R40) {
752 /* VTF enable (tpr13[8] == 1) */
170817a4 753 setbits_le32(&mctl_ctl->vtfcr,
8201188c
CYT
754 (socid != SOCID_A64 ? 3 : 2) << 8);
755 /* DQ hold disable (tpr13[26] == 1) */
1bc464be
JK
756 clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
757 }
0404d53f
JK
758
759 /* clear credit value */
760 setbits_le32(&mctl_com->cccr, 1 << 31);
761 udelay(10);
762
8201188c
CYT
763 mctl_auto_detect_dram_size(socid, &para);
764 mctl_set_cr(socid, &para);
0404d53f 765
66b12526
IZ
766 return (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
767 (para.dual_rank ? 2 : 1);
0404d53f 768}