blob: f5d8718fefff27281ecc340982973759b65d421e [file] [log] [blame]
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * sun50i H616 platform dram controller driver
4 *
5 * While controller is very similar to that in H6, PHY is completely
6 * unknown. That's why this driver has plenty of magic numbers. Some
7 * meaning was nevertheless deduced from strings found in boot0 and
8 * known meaning of some dram parameters.
9 * This driver only supports DDR3 memory and omits logic for all
10 * other supported types supported by hardware.
11 *
12 * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
13 *
14 */
15#include <common.h>
16#include <init.h>
17#include <log.h>
18#include <asm/io.h>
19#include <asm/arch/clock.h>
20#include <asm/arch/dram.h>
21#include <asm/arch/cpu.h>
Jernej Skrabece04cd492022-01-30 15:27:13 +010022#include <asm/arch/prcm.h>
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010023#include <linux/bitops.h>
24#include <linux/delay.h>
25#include <linux/kconfig.h>
26
27enum {
28 MBUS_QOS_LOWEST = 0,
29 MBUS_QOS_LOW,
30 MBUS_QOS_HIGH,
31 MBUS_QOS_HIGHEST
32};
33
34inline void mbus_configure_port(u8 port,
35 bool bwlimit,
36 bool priority,
37 u8 qos,
38 u8 waittime,
39 u8 acs,
40 u16 bwl0,
41 u16 bwl1,
42 u16 bwl2)
43{
44 struct sunxi_mctl_com_reg * const mctl_com =
45 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
46
47 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
48 | (priority ? (1 << 1) : 0)
49 | ((qos & 0x3) << 2)
50 | ((waittime & 0xf) << 4)
51 | ((acs & 0xff) << 8)
52 | (bwl0 << 16) );
53 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
54
55 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
56 writel_relaxed(cfg0, &mctl_com->master[port].cfg0);
57 writel_relaxed(cfg1, &mctl_com->master[port].cfg1);
58}
59
60#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
61 mbus_configure_port(port, bwlimit, false, \
62 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
63
64static void mctl_set_master_priority(void)
65{
66 struct sunxi_mctl_com_reg * const mctl_com =
67 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
68
69 /* enable bandwidth limit windows and set windows size 1us */
70 writel(399, &mctl_com->tmr);
71 writel(BIT(16), &mctl_com->bwcr);
72
73 MBUS_CONF( 0, true, HIGHEST, 0, 256, 128, 100);
74 MBUS_CONF( 1, true, HIGH, 0, 1536, 1400, 256);
75 MBUS_CONF( 2, true, HIGHEST, 0, 512, 256, 96);
76 MBUS_CONF( 3, true, HIGH, 0, 256, 100, 80);
77 MBUS_CONF( 4, true, HIGH, 2, 8192, 5500, 5000);
78 MBUS_CONF( 5, true, HIGH, 2, 100, 64, 32);
79 MBUS_CONF( 6, true, HIGH, 2, 100, 64, 32);
80 MBUS_CONF( 8, true, HIGH, 0, 256, 128, 64);
81 MBUS_CONF(11, true, HIGH, 0, 256, 128, 100);
82 MBUS_CONF(14, true, HIGH, 0, 1024, 256, 64);
83 MBUS_CONF(16, true, HIGHEST, 6, 8192, 2800, 2400);
84 MBUS_CONF(21, true, HIGHEST, 6, 2048, 768, 512);
85 MBUS_CONF(25, true, HIGHEST, 0, 100, 64, 32);
86 MBUS_CONF(26, true, HIGH, 2, 8192, 5500, 5000);
87 MBUS_CONF(37, true, HIGH, 0, 256, 128, 64);
88 MBUS_CONF(38, true, HIGH, 2, 100, 64, 32);
89 MBUS_CONF(39, true, HIGH, 2, 8192, 5500, 5000);
90 MBUS_CONF(40, true, HIGH, 2, 100, 64, 32);
91
92 dmb();
93}
94
95static void mctl_sys_init(struct dram_para *para)
96{
97 struct sunxi_ccm_reg * const ccm =
98 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
99 struct sunxi_mctl_com_reg * const mctl_com =
100 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
101 struct sunxi_mctl_ctl_reg * const mctl_ctl =
102 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
103
104 /* Put all DRAM-related blocks to reset state */
105 clrbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
106 clrbits_le32(&ccm->mbus_cfg, MBUS_RESET);
107 clrbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
108 udelay(5);
109 clrbits_le32(&ccm->dram_gate_reset, BIT(RESET_SHIFT));
110 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
111 clrbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
112
113 udelay(5);
114
115 /* Set PLL5 rate to doubled DRAM clock rate */
116 writel(CCM_PLL5_CTRL_EN | CCM_PLL5_LOCK_EN | CCM_PLL5_OUT_EN |
Andre Przywara0f7c8bc2021-05-05 13:53:05 +0100117 CCM_PLL5_CTRL_N(para->clk * 2 / 24), &ccm->pll5_cfg);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100118 mctl_await_completion(&ccm->pll5_cfg, CCM_PLL5_LOCK, CCM_PLL5_LOCK);
119
120 /* Configure DRAM mod clock */
121 writel(DRAM_CLK_SRC_PLL5, &ccm->dram_clk_cfg);
122 writel(BIT(RESET_SHIFT), &ccm->dram_gate_reset);
123 udelay(5);
124 setbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
125
126 /* Disable all channels */
127 writel(0, &mctl_com->maer0);
128 writel(0, &mctl_com->maer1);
129 writel(0, &mctl_com->maer2);
130
131 /* Configure MBUS and enable DRAM mod reset */
132 setbits_le32(&ccm->mbus_cfg, MBUS_RESET);
133 setbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
134
135 clrbits_le32(&mctl_com->unk_0x500, BIT(25));
136
137 setbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
138 udelay(5);
139
140 /* Unknown hack, which enables access of mctl_ctl regs */
141 writel(0x8000, &mctl_ctl->clken);
142}
143
144static void mctl_set_addrmap(struct dram_para *para)
145{
146 struct sunxi_mctl_ctl_reg * const mctl_ctl =
147 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
148 u8 cols = para->cols;
149 u8 rows = para->rows;
150 u8 ranks = para->ranks;
151
152 if (!para->bus_full_width)
153 cols -= 1;
154
155 /* Ranks */
156 if (ranks == 2)
157 mctl_ctl->addrmap[0] = rows + cols - 3;
158 else
159 mctl_ctl->addrmap[0] = 0x1F;
160
161 /* Banks, hardcoded to 8 banks now */
162 mctl_ctl->addrmap[1] = (cols - 2) | (cols - 2) << 8 | (cols - 2) << 16;
163
164 /* Columns */
165 mctl_ctl->addrmap[2] = 0;
166 switch (cols) {
167 case 7:
168 mctl_ctl->addrmap[3] = 0x1F1F1F00;
169 mctl_ctl->addrmap[4] = 0x1F1F;
170 break;
171 case 8:
172 mctl_ctl->addrmap[3] = 0x1F1F0000;
173 mctl_ctl->addrmap[4] = 0x1F1F;
174 break;
175 case 9:
176 mctl_ctl->addrmap[3] = 0x1F000000;
177 mctl_ctl->addrmap[4] = 0x1F1F;
178 break;
179 case 10:
180 mctl_ctl->addrmap[3] = 0;
181 mctl_ctl->addrmap[4] = 0x1F1F;
182 break;
183 case 11:
184 mctl_ctl->addrmap[3] = 0;
185 mctl_ctl->addrmap[4] = 0x1F00;
186 break;
187 case 12:
188 mctl_ctl->addrmap[3] = 0;
189 mctl_ctl->addrmap[4] = 0;
190 break;
191 default:
192 panic("Unsupported DRAM configuration: column number invalid\n");
193 }
194
195 /* Rows */
196 mctl_ctl->addrmap[5] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
197 switch (rows) {
198 case 13:
199 mctl_ctl->addrmap[6] = (cols - 3) | 0x0F0F0F00;
200 mctl_ctl->addrmap[7] = 0x0F0F;
201 break;
202 case 14:
203 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | 0x0F0F0000;
204 mctl_ctl->addrmap[7] = 0x0F0F;
205 break;
206 case 15:
207 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | 0x0F000000;
208 mctl_ctl->addrmap[7] = 0x0F0F;
209 break;
210 case 16:
211 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
212 mctl_ctl->addrmap[7] = 0x0F0F;
213 break;
214 case 17:
215 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
216 mctl_ctl->addrmap[7] = (cols - 3) | 0x0F00;
217 break;
218 case 18:
219 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
220 mctl_ctl->addrmap[7] = (cols - 3) | ((cols - 3) << 8);
221 break;
222 default:
223 panic("Unsupported DRAM configuration: row number invalid\n");
224 }
225
226 /* Bank groups, DDR4 only */
227 mctl_ctl->addrmap[8] = 0x3F3F;
228}
229
230static const u8 phy_init[] = {
231 0x07, 0x0b, 0x02, 0x16, 0x0d, 0x0e, 0x14, 0x19,
232 0x0a, 0x15, 0x03, 0x13, 0x04, 0x0c, 0x10, 0x06,
233 0x0f, 0x11, 0x1a, 0x01, 0x12, 0x17, 0x00, 0x08,
234 0x09, 0x05, 0x18
235};
236
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200237static void mctl_phy_configure_odt(struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100238{
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200239 unsigned int val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100240
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200241 val = para->dx_dri & 0x1f;
242 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x388);
243 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x38c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100244
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200245 val = (para->dx_dri >> 8) & 0x1f;
246 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c8);
247 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3cc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100248
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200249 val = (para->dx_dri >> 16) & 0x1f;
250 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x408);
251 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x40c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100252
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200253 val = (para->dx_dri >> 24) & 0x1f;
254 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x448);
255 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x44c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100256
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200257 val = para->ca_dri & 0x1f;
258 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x340);
259 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x344);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100260
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200261 val = (para->ca_dri >> 8) & 0x1f;
262 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x348);
263 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x34c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100264
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200265 val = para->dx_odt & 0x1f;
266 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x380);
267 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x384);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100268
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200269 val = (para->dx_odt >> 8) & 0x1f;
270 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c0);
271 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100272
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200273 val = (para->dx_odt >> 16) & 0x1f;
274 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x400);
275 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x404);
276
277 val = (para->dx_odt >> 24) & 0x1f;
278 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x440);
279 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x444);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100280
281 dmb();
282}
283
284static bool mctl_phy_write_leveling(struct dram_para *para)
285{
286 bool result = true;
287 u32 val;
288
289 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x80);
290 writel(4, SUNXI_DRAM_PHY0_BASE + 0xc);
291 writel(0x40, SUNXI_DRAM_PHY0_BASE + 0x10);
292
293 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
294
295 if (para->bus_full_width)
296 val = 0xf;
297 else
298 val = 3;
299
Jernej Skrabec5a088482023-04-10 10:21:11 +0200300 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100301
302 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
303
304 val = readl(SUNXI_DRAM_PHY0_BASE + 0x258);
305 if (val == 0 || val == 0x3f)
306 result = false;
307 val = readl(SUNXI_DRAM_PHY0_BASE + 0x25c);
308 if (val == 0 || val == 0x3f)
309 result = false;
310 val = readl(SUNXI_DRAM_PHY0_BASE + 0x318);
311 if (val == 0 || val == 0x3f)
312 result = false;
313 val = readl(SUNXI_DRAM_PHY0_BASE + 0x31c);
314 if (val == 0 || val == 0x3f)
315 result = false;
316
317 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
318
319 if (para->ranks == 2) {
320 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
321
322 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
323
324 if (para->bus_full_width)
325 val = 0xf;
326 else
327 val = 3;
328
Jernej Skrabec5a088482023-04-10 10:21:11 +0200329 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100330
331 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
332 }
333
334 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
335
336 return result;
337}
338
339static bool mctl_phy_read_calibration(struct dram_para *para)
340{
341 bool result = true;
342 u32 val, tmp;
343
344 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
345
346 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
347
348 if (para->bus_full_width)
349 val = 0xf;
350 else
351 val = 3;
352
353 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
354 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
355 result = false;
356 break;
357 }
358 }
359
360 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
361
362 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
363
364 if (para->ranks == 2) {
365 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
366
367 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
368
369 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
370 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
371 result = false;
372 break;
373 }
374 }
375
Jernej Skrabec4e048422022-01-29 16:58:43 +0100376 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100377 }
378
379 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
380
381 val = readl(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
382 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
383 if (val < tmp)
384 val = tmp;
385 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
386 if (val < tmp)
387 val = tmp;
388 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
389 if (val < tmp)
390 val = tmp;
391 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
392
393 setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
394
395 return result;
396}
397
398static bool mctl_phy_read_training(struct dram_para *para)
399{
400 u32 val1, val2, *ptr1, *ptr2;
401 bool result = true;
402 int i;
403
404 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
405 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x804, 0x3f, 0xf);
406 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x808, 0x3f, 0xf);
407 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa04, 0x3f, 0xf);
408 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa08, 0x3f, 0xf);
409
410 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
411 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
412
Jernej Skrabec5a088482023-04-10 10:21:11 +0200413 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100414 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
415 result = false;
416
417 if (para->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200418 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100419 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
420 result = false;
421 }
422
Jernej Skrabec5a088482023-04-10 10:21:11 +0200423 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x898);
424 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x850);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100425 for (i = 0; i < 9; i++) {
426 val1 = readl(&ptr1[i]);
427 val2 = readl(&ptr2[i]);
428 if (val1 - val2 <= 6)
429 result = false;
430 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200431 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
432 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x874);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100433 for (i = 0; i < 9; i++) {
434 val1 = readl(&ptr1[i]);
435 val2 = readl(&ptr2[i]);
436 if (val1 - val2 <= 6)
437 result = false;
438 }
439
440 if (para->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200441 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
442 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100443 for (i = 0; i < 9; i++) {
444 val1 = readl(&ptr1[i]);
445 val2 = readl(&ptr2[i]);
446 if (val1 - val2 <= 6)
447 result = false;
448 }
449
Jernej Skrabec5a088482023-04-10 10:21:11 +0200450 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xabc);
451 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100452 for (i = 0; i < 9; i++) {
453 val1 = readl(&ptr1[i]);
454 val2 = readl(&ptr2[i]);
455 if (val1 - val2 <= 6)
456 result = false;
457 }
458 }
459
460 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
461
462 if (para->ranks == 2) {
463 /* maybe last parameter should be 1? */
464 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
465
466 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
467 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
468
Jernej Skrabec5a088482023-04-10 10:21:11 +0200469 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100470 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
471 result = false;
472
473 if (para->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200474 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100475 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
476 result = false;
477 }
478
479 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
480 }
481
482 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3);
483
484 return result;
485}
486
487static bool mctl_phy_write_training(struct dram_para *para)
488{
489 u32 val1, val2, *ptr1, *ptr2;
490 bool result = true;
491 int i;
492
493 writel(0, SUNXI_DRAM_PHY0_BASE + 0x134);
494 writel(0, SUNXI_DRAM_PHY0_BASE + 0x138);
495 writel(0, SUNXI_DRAM_PHY0_BASE + 0x19c);
496 writel(0, SUNXI_DRAM_PHY0_BASE + 0x1a0);
497
498 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 8);
499
500 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
501 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
502
Jernej Skrabec5a088482023-04-10 10:21:11 +0200503 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100504 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
505 result = false;
506
507 if (para->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200508 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100509 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
510 result = false;
511 }
512
Jernej Skrabec5a088482023-04-10 10:21:11 +0200513 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x938);
514 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100515 for (i = 0; i < 9; i++) {
516 val1 = readl(&ptr1[i]);
517 val2 = readl(&ptr2[i]);
518 if (val1 - val2 <= 6)
519 result = false;
520 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200521 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x95c);
522 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x914);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100523 for (i = 0; i < 9; i++) {
524 val1 = readl(&ptr1[i]);
525 val2 = readl(&ptr2[i]);
526 if (val1 - val2 <= 6)
527 result = false;
528 }
529
530 if (para->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200531 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
532 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100533 for (i = 0; i < 9; i++) {
534 val1 = readl(&ptr1[i]);
535 val2 = readl(&ptr2[i]);
536 if (val1 - val2 <= 6)
537 result = false;
538 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200539 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
540 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100541 for (i = 0; i < 9; i++) {
542 val1 = readl(&ptr1[i]);
543 val2 = readl(&ptr2[i]);
544 if (val1 - val2 <= 6)
545 result = false;
546 }
547 }
548
549 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
550
551 if (para->ranks == 2) {
552 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
553
554 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
555 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
556
Jernej Skrabec5a088482023-04-10 10:21:11 +0200557 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100558 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
559 result = false;
560
561 if (para->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200562 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100563 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
564 result = false;
565 }
566
567 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
568 }
569
570 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc);
571
572 return result;
573}
574
Jernej Skrabec47e263e2023-04-10 10:21:15 +0200575static void mctl_phy_bit_delay_compensation(struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100576{
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200577 u32 *ptr, val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100578 int i;
579
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200580 if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
581 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
582 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
583 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100584
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200585 if (para->tpr10 & BIT(30))
586 val = para->tpr11 & 0x3f;
587 else
588 val = (para->tpr11 & 0xf) << 1;
589
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200590 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484);
591 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200592 writel_relaxed(val, ptr);
593 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200594 ptr += 2;
595 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200596
597 if (para->tpr10 & BIT(30))
598 val = (para->odt_en >> 15) & 0x1e;
599 else
600 val = (para->tpr11 >> 15) & 0x1e;
601
602 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4d0);
603 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x590);
604 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4cc);
605 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x58c);
606
607 if (para->tpr10 & BIT(30))
608 val = (para->tpr11 >> 8) & 0x3f;
609 else
610 val = (para->tpr11 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100611
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200612 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
613 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200614 writel_relaxed(val, ptr);
615 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200616 ptr += 2;
617 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200618
619 if (para->tpr10 & BIT(30))
620 val = (para->odt_en >> 19) & 0x1e;
621 else
622 val = (para->tpr11 >> 19) & 0x1e;
623
624 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x524);
625 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e4);
626 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x520);
627 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e0);
628
629 if (para->tpr10 & BIT(30))
630 val = (para->tpr11 >> 16) & 0x3f;
631 else
632 val = (para->tpr11 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100633
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200634 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604);
635 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200636 writel_relaxed(val, ptr);
637 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200638 ptr += 2;
639 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200640
641 if (para->tpr10 & BIT(30))
642 val = (para->odt_en >> 23) & 0x1e;
643 else
644 val = (para->tpr11 >> 23) & 0x1e;
645
646 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x650);
647 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x710);
648 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x64c);
649 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x70c);
650
651 if (para->tpr10 & BIT(30))
652 val = (para->tpr11 >> 24) & 0x3f;
653 else
654 val = (para->tpr11 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100655
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200656 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658);
657 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200658 writel_relaxed(val, ptr);
659 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200660 ptr += 2;
661 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200662
663 if (para->tpr10 & BIT(30))
664 val = (para->odt_en >> 27) & 0x1e;
665 else
666 val = (para->tpr11 >> 27) & 0x1e;
667
668 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a4);
669 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x764);
670 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a0);
671 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x760);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100672
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200673 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100674
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200675 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
676 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100677
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200678 if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
679 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
680 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100681
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200682 if (para->tpr10 & BIT(30))
683 val = para->tpr12 & 0x3f;
684 else
685 val = (para->tpr12 & 0xf) << 1;
686
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200687 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480);
688 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200689 writel_relaxed(val, ptr);
690 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200691 ptr += 2;
692 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200693
694 if (para->tpr10 & BIT(30))
695 val = (para->odt_en << 1) & 0x1e;
696 else
697 val = (para->tpr12 >> 15) & 0x1e;
698
699 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x528);
700 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e8);
701 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4c8);
702 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x588);
703
704 if (para->tpr10 & BIT(30))
705 val = (para->tpr12 >> 8) & 0x3f;
706 else
707 val = (para->tpr12 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100708
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200709 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
710 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200711 writel_relaxed(val, ptr);
712 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200713 ptr += 2;
714 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200715
716 if (para->tpr10 & BIT(30))
717 val = (para->odt_en >> 3) & 0x1e;
718 else
719 val = (para->tpr12 >> 19) & 0x1e;
720
721 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x52c);
722 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5ec);
723 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x51c);
724 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5dc);
725
726 if (para->tpr10 & BIT(30))
727 val = (para->tpr12 >> 16) & 0x3f;
728 else
729 val = (para->tpr12 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100730
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200731 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600);
732 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200733 writel_relaxed(val, ptr);
734 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200735 ptr += 2;
736 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200737
738 if (para->tpr10 & BIT(30))
739 val = (para->odt_en >> 7) & 0x1e;
740 else
741 val = (para->tpr12 >> 23) & 0x1e;
742
743 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a8);
744 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x768);
745 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x648);
746 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x708);
747
748 if (para->tpr10 & BIT(30))
749 val = (para->tpr12 >> 24) & 0x3f;
750 else
751 val = (para->tpr12 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100752
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200753 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
754 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200755 writel_relaxed(val, ptr);
756 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200757 ptr += 2;
758 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200759
760 if (para->tpr10 & BIT(30))
761 val = (para->odt_en >> 11) & 0x1e;
762 else
763 val = (para->tpr12 >> 27) & 0x1e;
764
765 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6ac);
766 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x76c);
767 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x69c);
768 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x75c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100769
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200770 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100771
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200772 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
773 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100774}
775
776static bool mctl_phy_init(struct dram_para *para)
777{
778 struct sunxi_mctl_com_reg * const mctl_com =
779 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
780 struct sunxi_mctl_ctl_reg * const mctl_ctl =
781 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
782 u32 val, *ptr;
783 int i;
784
785 if (para->bus_full_width)
786 val = 0xf;
787 else
788 val = 3;
789 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
790
791 writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x14);
792 writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x35c);
793 writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x368);
794 writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x374);
795
796 writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
797 writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
798 writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
799 writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
800
801 writel(9, SUNXI_DRAM_PHY0_BASE + 0x1c);
802 writel(9, SUNXI_DRAM_PHY0_BASE + 0x364);
803 writel(9, SUNXI_DRAM_PHY0_BASE + 0x370);
804 writel(9, SUNXI_DRAM_PHY0_BASE + 0x37c);
805
Jernej Skrabec5a088482023-04-10 10:21:11 +0200806 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100807 for (i = 0; i < ARRAY_SIZE(phy_init); i++)
808 writel(phy_init[i], &ptr[i]);
809
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200810 if (para->tpr10 & TPR10_CA_BIT_DELAY) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200811 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100812 for (i = 0; i < 32; i++)
813 writel(0x16, &ptr[i]);
814 writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x78c);
815 writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7a4);
816 writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7b8);
817 writel(0x8, SUNXI_DRAM_PHY0_BASE + 0x7d4);
818 writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7dc);
819 writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7e0);
820 }
821
822 writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);
823 writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x45c);
824
Jernej Skrabec64712da2023-04-10 10:21:14 +0200825 mctl_phy_configure_odt(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100826
827 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa);
828
829 if (para->clk <= 672)
830 writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
831 if (para->clk > 500) {
832 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
833 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
834 } else {
835 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
836 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
837 }
838
839 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
840
Jernej Skrabec5a088482023-04-10 10:21:11 +0200841 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100842
843 writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
844 clrbits_le32(&mctl_com->unk_0x500, 0x200);
845
846 writel(0, &mctl_ctl->swctl);
847 setbits_le32(&mctl_ctl->dfimisc, 1);
848
849 /* start DFI init */
850 setbits_le32(&mctl_ctl->dfimisc, 0x20);
851 writel(1, &mctl_ctl->swctl);
852 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
853 /* poll DFI init complete */
854 mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
855 writel(0, &mctl_ctl->swctl);
856 clrbits_le32(&mctl_ctl->dfimisc, 0x20);
857
858 clrbits_le32(&mctl_ctl->pwrctl, 0x20);
859 writel(1, &mctl_ctl->swctl);
860 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
861 mctl_await_completion(&mctl_ctl->statr, 3, 1);
862
863 writel(0, &mctl_ctl->swctl);
864 clrbits_le32(&mctl_ctl->dfimisc, 1);
865
866 writel(1, &mctl_ctl->swctl);
867 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
868
869 writel(0x1f14, &mctl_ctl->mrctrl1);
870 writel(0x80000030, &mctl_ctl->mrctrl0);
871 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
872
873 writel(4, &mctl_ctl->mrctrl1);
874 writel(0x80001030, &mctl_ctl->mrctrl0);
875 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
876
877 writel(0x20, &mctl_ctl->mrctrl1);
878 writel(0x80002030, &mctl_ctl->mrctrl0);
879 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
880
881 writel(0, &mctl_ctl->mrctrl1);
882 writel(0x80003030, &mctl_ctl->mrctrl0);
883 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
884
885 writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
886
887 writel(0, &mctl_ctl->swctl);
888 clrbits_le32(&mctl_ctl->rfshctl3, 1);
889 writel(1, &mctl_ctl->swctl);
890
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200891 if (para->tpr10 & TPR10_WRITE_LEVELING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100892 for (i = 0; i < 5; i++)
893 if (mctl_phy_write_leveling(para))
894 break;
895 if (i == 5) {
896 debug("write leveling failed!\n");
897 return false;
898 }
899 }
900
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200901 if (para->tpr10 & TPR10_READ_CALIBRATION) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100902 for (i = 0; i < 5; i++)
903 if (mctl_phy_read_calibration(para))
904 break;
905 if (i == 5) {
906 debug("read calibration failed!\n");
907 return false;
908 }
909 }
910
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200911 if (para->tpr10 & TPR10_READ_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100912 for (i = 0; i < 5; i++)
913 if (mctl_phy_read_training(para))
914 break;
915 if (i == 5) {
916 debug("read training failed!\n");
917 return false;
918 }
919 }
920
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200921 if (para->tpr10 & TPR10_WRITE_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100922 for (i = 0; i < 5; i++)
923 if (mctl_phy_write_training(para))
924 break;
925 if (i == 5) {
926 debug("write training failed!\n");
927 return false;
928 }
929 }
930
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200931 mctl_phy_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100932
933 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
934
935 return true;
936}
937
938static bool mctl_ctrl_init(struct dram_para *para)
939{
940 struct sunxi_mctl_com_reg * const mctl_com =
941 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
942 struct sunxi_mctl_ctl_reg * const mctl_ctl =
943 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
944 u32 reg_val;
945
946 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
947 writel(0x8000, &mctl_ctl->clken);
948
949 setbits_le32(&mctl_com->unk_0x008, 0xff00);
950
951 clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
952
953 writel(0, &mctl_ctl->hwlpctl);
954
955 setbits_le32(&mctl_com->unk_0x008, 0xff00);
956
957 reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks);
958 reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
959 if (para->bus_full_width)
960 reg_val |= MSTR_BUSWIDTH_FULL;
961 else
962 reg_val |= MSTR_BUSWIDTH_HALF;
963 writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
964
965 if (para->ranks == 2)
966 writel(0x0303, &mctl_ctl->odtmap);
967 else
968 writel(0x0201, &mctl_ctl->odtmap);
969
970 writel(0x06000400, &mctl_ctl->odtcfg);
971 writel(0x06000400, &mctl_ctl->unk_0x2240);
972 writel(0x06000400, &mctl_ctl->unk_0x3240);
973 writel(0x06000400, &mctl_ctl->unk_0x4240);
974
Jernej Skrabec472d4042023-04-10 10:21:10 +0200975 writel(BIT(31), &mctl_com->cr);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100976
977 mctl_set_addrmap(para);
978
979 mctl_set_timing_params(para);
980
981 writel(0, &mctl_ctl->pwrctl);
982
983 setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
984 setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
985 setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
986 setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
987 setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
988
989 setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
990 clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
991
992 writel(0, &mctl_com->maer0);
993 writel(0, &mctl_com->maer1);
994 writel(0, &mctl_com->maer2);
995
996 writel(0x20, &mctl_ctl->pwrctl);
997 setbits_le32(&mctl_ctl->clken, BIT(8));
998
999 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
1000 /* this write seems to enable PHY MMIO region */
1001 setbits_le32(&mctl_com->unk_0x500, BIT(24));
1002
1003 if (!mctl_phy_init(para))
1004 return false;
1005
1006 writel(0, &mctl_ctl->swctl);
1007 clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1008
1009 setbits_le32(&mctl_com->unk_0x014, BIT(31));
1010 writel(0xffffffff, &mctl_com->maer0);
1011 writel(0x7ff, &mctl_com->maer1);
1012 writel(0xffff, &mctl_com->maer2);
1013
1014 writel(1, &mctl_ctl->swctl);
1015 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1016
1017 return true;
1018}
1019
1020static bool mctl_core_init(struct dram_para *para)
1021{
1022 mctl_sys_init(para);
1023
1024 return mctl_ctrl_init(para);
1025}
1026
1027static void mctl_auto_detect_rank_width(struct dram_para *para)
1028{
1029 /* this is minimum size that it's supported */
1030 para->cols = 8;
1031 para->rows = 13;
1032
1033 /*
1034 * Strategy here is to test most demanding combination first and least
1035 * demanding last, otherwise HW might not be fully utilized. For
1036 * example, half bus width and rank = 1 combination would also work
1037 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
1038 * visible.
1039 */
1040
1041 debug("testing 32-bit width, rank = 2\n");
1042 para->bus_full_width = 1;
1043 para->ranks = 2;
1044 if (mctl_core_init(para))
1045 return;
1046
1047 debug("testing 32-bit width, rank = 1\n");
1048 para->bus_full_width = 1;
1049 para->ranks = 1;
1050 if (mctl_core_init(para))
1051 return;
1052
1053 debug("testing 16-bit width, rank = 2\n");
1054 para->bus_full_width = 0;
1055 para->ranks = 2;
1056 if (mctl_core_init(para))
1057 return;
1058
1059 debug("testing 16-bit width, rank = 1\n");
1060 para->bus_full_width = 0;
1061 para->ranks = 1;
1062 if (mctl_core_init(para))
1063 return;
1064
1065 panic("This DRAM setup is currently not supported.\n");
1066}
1067
1068static void mctl_auto_detect_dram_size(struct dram_para *para)
1069{
1070 /* detect row address bits */
1071 para->cols = 8;
1072 para->rows = 18;
1073 mctl_core_init(para);
1074
1075 for (para->rows = 13; para->rows < 18; para->rows++) {
1076 /* 8 banks, 8 bit per byte and 16/32 bit width */
1077 if (mctl_mem_matches((1 << (para->rows + para->cols +
1078 4 + para->bus_full_width))))
1079 break;
1080 }
1081
1082 /* detect column address bits */
1083 para->cols = 11;
1084 mctl_core_init(para);
1085
1086 for (para->cols = 8; para->cols < 11; para->cols++) {
1087 /* 8 bits per byte and 16/32 bit width */
1088 if (mctl_mem_matches(1 << (para->cols + 1 +
1089 para->bus_full_width)))
1090 break;
1091 }
1092}
1093
1094static unsigned long mctl_calc_size(struct dram_para *para)
1095{
1096 u8 width = para->bus_full_width ? 4 : 2;
1097
1098 /* 8 banks */
1099 return (1ULL << (para->cols + para->rows + 3)) * width * para->ranks;
1100}
1101
1102unsigned long sunxi_dram_init(void)
1103{
Jernej Skrabece04cd492022-01-30 15:27:13 +01001104 struct sunxi_prcm_reg *const prcm =
1105 (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001106 struct dram_para para = {
1107 .clk = CONFIG_DRAM_CLK,
1108 .type = SUNXI_DRAM_TYPE_DDR3,
Jernej Skrabecdd533da2023-04-10 10:21:12 +02001109 .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
1110 .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
1111 .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
Jernej Skrabec63ab9552023-04-10 10:21:16 +02001112 .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001113 .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
Jernej Skrabec63ab9552023-04-10 10:21:16 +02001114 .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
1115 .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001116 };
1117 unsigned long size;
1118
Jernej Skrabece04cd492022-01-30 15:27:13 +01001119 setbits_le32(&prcm->res_cal_ctrl, BIT(8));
1120 clrbits_le32(&prcm->ohms240, 0x3f);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001121
1122 mctl_auto_detect_rank_width(&para);
1123 mctl_auto_detect_dram_size(&para);
1124
1125 mctl_core_init(&para);
1126
1127 size = mctl_calc_size(&para);
1128
1129 mctl_set_master_priority();
1130
1131 return size;
1132};