blob: 1f9416d6eaf5aad712e2fda8ce7d4d316ff314ab [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
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200776static void mctl_phy_ca_bit_delay_compensation(struct dram_para *para)
777{
778 u32 val, *ptr;
779 int i;
780
781 if (para->tpr0 & BIT(30))
782 val = (para->tpr0 >> 7) & 0x3e;
783 else
784 val = (para->tpr10 >> 3) & 0x1e;
785
786 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
787 for (i = 0; i < 32; i++)
788 writel(val, &ptr[i]);
789
790 val = (para->tpr10 << 1) & 0x1e;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200791 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200792 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
793 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200794 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200795
796 /* following configuration is DDR3 specific */
797 val = (para->tpr10 >> 7) & 0x1e;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200798 if (para->tpr2 & 1) {
799 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
800 if (para->ranks == 2) {
801 val = (para->tpr10 >> 11) & 0x1e;
802 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
803 }
804 if (para->tpr0 & BIT(31)) {
805 val = (para->tpr0 << 1) & 0x3e;
806 writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
807 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
808 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
809 }
810 } else {
811 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
812 if (para->ranks == 2) {
813 val = (para->tpr10 >> 11) & 0x1e;
814 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
815 }
816 if (para->tpr0 & BIT(31)) {
817 val = (para->tpr0 << 1) & 0x3e;
818 writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
819 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
820 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
821 }
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200822 }
823}
824
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100825static bool mctl_phy_init(struct dram_para *para)
826{
827 struct sunxi_mctl_com_reg * const mctl_com =
828 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
829 struct sunxi_mctl_ctl_reg * const mctl_ctl =
830 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200831 u32 val, val2, *ptr, mr0, mr2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100832 int i;
833
834 if (para->bus_full_width)
835 val = 0xf;
836 else
837 val = 3;
838 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
839
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200840 if (para->tpr2 & 0x100) {
841 val = 9;
842 val2 = 7;
843 } else {
844 val = 13;
845 val2 = 9;
846 }
847
848 writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
849 writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
850 writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
851 writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100852
853 writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
854 writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
855 writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
856 writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
857
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200858 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
859 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
860 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
861 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100862
Jernej Skrabec5a088482023-04-10 10:21:11 +0200863 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100864 for (i = 0; i < ARRAY_SIZE(phy_init); i++)
865 writel(phy_init[i], &ptr[i]);
866
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200867 if (para->tpr10 & TPR10_CA_BIT_DELAY)
868 mctl_phy_ca_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100869
870 writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);
871 writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x45c);
872
Jernej Skrabec64712da2023-04-10 10:21:14 +0200873 mctl_phy_configure_odt(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100874
875 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa);
876
877 if (para->clk <= 672)
878 writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
879 if (para->clk > 500) {
880 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
881 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
882 } else {
883 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
884 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
885 }
886
887 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
888
Jernej Skrabec5a088482023-04-10 10:21:11 +0200889 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100890
891 writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
892 clrbits_le32(&mctl_com->unk_0x500, 0x200);
893
894 writel(0, &mctl_ctl->swctl);
895 setbits_le32(&mctl_ctl->dfimisc, 1);
896
897 /* start DFI init */
898 setbits_le32(&mctl_ctl->dfimisc, 0x20);
899 writel(1, &mctl_ctl->swctl);
900 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
901 /* poll DFI init complete */
902 mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
903 writel(0, &mctl_ctl->swctl);
904 clrbits_le32(&mctl_ctl->dfimisc, 0x20);
905
906 clrbits_le32(&mctl_ctl->pwrctl, 0x20);
907 writel(1, &mctl_ctl->swctl);
908 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
909 mctl_await_completion(&mctl_ctl->statr, 3, 1);
910
911 writel(0, &mctl_ctl->swctl);
912 clrbits_le32(&mctl_ctl->dfimisc, 1);
913
914 writel(1, &mctl_ctl->swctl);
915 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
916
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200917 if (para->tpr2 & 0x100) {
918 mr0 = 0x1b50;
919 mr2 = 0x10;
920 } else {
921 mr0 = 0x1f14;
922 mr2 = 0x20;
923 }
924
925 writel(mr0, &mctl_ctl->mrctrl1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100926 writel(0x80000030, &mctl_ctl->mrctrl0);
927 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
928
929 writel(4, &mctl_ctl->mrctrl1);
930 writel(0x80001030, &mctl_ctl->mrctrl0);
931 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
932
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200933 writel(mr2, &mctl_ctl->mrctrl1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100934 writel(0x80002030, &mctl_ctl->mrctrl0);
935 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
936
937 writel(0, &mctl_ctl->mrctrl1);
938 writel(0x80003030, &mctl_ctl->mrctrl0);
939 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
940
941 writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
942
943 writel(0, &mctl_ctl->swctl);
944 clrbits_le32(&mctl_ctl->rfshctl3, 1);
945 writel(1, &mctl_ctl->swctl);
946
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200947 if (para->tpr10 & TPR10_WRITE_LEVELING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100948 for (i = 0; i < 5; i++)
949 if (mctl_phy_write_leveling(para))
950 break;
951 if (i == 5) {
952 debug("write leveling failed!\n");
953 return false;
954 }
955 }
956
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200957 if (para->tpr10 & TPR10_READ_CALIBRATION) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100958 for (i = 0; i < 5; i++)
959 if (mctl_phy_read_calibration(para))
960 break;
961 if (i == 5) {
962 debug("read calibration failed!\n");
963 return false;
964 }
965 }
966
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200967 if (para->tpr10 & TPR10_READ_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100968 for (i = 0; i < 5; i++)
969 if (mctl_phy_read_training(para))
970 break;
971 if (i == 5) {
972 debug("read training failed!\n");
973 return false;
974 }
975 }
976
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200977 if (para->tpr10 & TPR10_WRITE_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100978 for (i = 0; i < 5; i++)
979 if (mctl_phy_write_training(para))
980 break;
981 if (i == 5) {
982 debug("write training failed!\n");
983 return false;
984 }
985 }
986
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200987 mctl_phy_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100988
989 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
990
991 return true;
992}
993
994static bool mctl_ctrl_init(struct dram_para *para)
995{
996 struct sunxi_mctl_com_reg * const mctl_com =
997 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
998 struct sunxi_mctl_ctl_reg * const mctl_ctl =
999 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
1000 u32 reg_val;
1001
1002 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
1003 writel(0x8000, &mctl_ctl->clken);
1004
1005 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1006
1007 clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
1008
1009 writel(0, &mctl_ctl->hwlpctl);
1010
1011 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1012
1013 reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks);
1014 reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
1015 if (para->bus_full_width)
1016 reg_val |= MSTR_BUSWIDTH_FULL;
1017 else
1018 reg_val |= MSTR_BUSWIDTH_HALF;
1019 writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
1020
1021 if (para->ranks == 2)
1022 writel(0x0303, &mctl_ctl->odtmap);
1023 else
1024 writel(0x0201, &mctl_ctl->odtmap);
1025
1026 writel(0x06000400, &mctl_ctl->odtcfg);
1027 writel(0x06000400, &mctl_ctl->unk_0x2240);
1028 writel(0x06000400, &mctl_ctl->unk_0x3240);
1029 writel(0x06000400, &mctl_ctl->unk_0x4240);
1030
Jernej Skrabec472d4042023-04-10 10:21:10 +02001031 writel(BIT(31), &mctl_com->cr);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001032
1033 mctl_set_addrmap(para);
1034
1035 mctl_set_timing_params(para);
1036
1037 writel(0, &mctl_ctl->pwrctl);
1038
1039 setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
1040 setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
1041 setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
1042 setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
1043 setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
1044
1045 setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1046 clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
1047
1048 writel(0, &mctl_com->maer0);
1049 writel(0, &mctl_com->maer1);
1050 writel(0, &mctl_com->maer2);
1051
1052 writel(0x20, &mctl_ctl->pwrctl);
1053 setbits_le32(&mctl_ctl->clken, BIT(8));
1054
1055 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
1056 /* this write seems to enable PHY MMIO region */
1057 setbits_le32(&mctl_com->unk_0x500, BIT(24));
1058
1059 if (!mctl_phy_init(para))
1060 return false;
1061
1062 writel(0, &mctl_ctl->swctl);
1063 clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1064
1065 setbits_le32(&mctl_com->unk_0x014, BIT(31));
1066 writel(0xffffffff, &mctl_com->maer0);
1067 writel(0x7ff, &mctl_com->maer1);
1068 writel(0xffff, &mctl_com->maer2);
1069
1070 writel(1, &mctl_ctl->swctl);
1071 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1072
1073 return true;
1074}
1075
1076static bool mctl_core_init(struct dram_para *para)
1077{
1078 mctl_sys_init(para);
1079
1080 return mctl_ctrl_init(para);
1081}
1082
1083static void mctl_auto_detect_rank_width(struct dram_para *para)
1084{
1085 /* this is minimum size that it's supported */
1086 para->cols = 8;
1087 para->rows = 13;
1088
1089 /*
1090 * Strategy here is to test most demanding combination first and least
1091 * demanding last, otherwise HW might not be fully utilized. For
1092 * example, half bus width and rank = 1 combination would also work
1093 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
1094 * visible.
1095 */
1096
1097 debug("testing 32-bit width, rank = 2\n");
1098 para->bus_full_width = 1;
1099 para->ranks = 2;
1100 if (mctl_core_init(para))
1101 return;
1102
1103 debug("testing 32-bit width, rank = 1\n");
1104 para->bus_full_width = 1;
1105 para->ranks = 1;
1106 if (mctl_core_init(para))
1107 return;
1108
1109 debug("testing 16-bit width, rank = 2\n");
1110 para->bus_full_width = 0;
1111 para->ranks = 2;
1112 if (mctl_core_init(para))
1113 return;
1114
1115 debug("testing 16-bit width, rank = 1\n");
1116 para->bus_full_width = 0;
1117 para->ranks = 1;
1118 if (mctl_core_init(para))
1119 return;
1120
1121 panic("This DRAM setup is currently not supported.\n");
1122}
1123
1124static void mctl_auto_detect_dram_size(struct dram_para *para)
1125{
1126 /* detect row address bits */
1127 para->cols = 8;
1128 para->rows = 18;
1129 mctl_core_init(para);
1130
1131 for (para->rows = 13; para->rows < 18; para->rows++) {
1132 /* 8 banks, 8 bit per byte and 16/32 bit width */
1133 if (mctl_mem_matches((1 << (para->rows + para->cols +
1134 4 + para->bus_full_width))))
1135 break;
1136 }
1137
1138 /* detect column address bits */
1139 para->cols = 11;
1140 mctl_core_init(para);
1141
1142 for (para->cols = 8; para->cols < 11; para->cols++) {
1143 /* 8 bits per byte and 16/32 bit width */
1144 if (mctl_mem_matches(1 << (para->cols + 1 +
1145 para->bus_full_width)))
1146 break;
1147 }
1148}
1149
1150static unsigned long mctl_calc_size(struct dram_para *para)
1151{
1152 u8 width = para->bus_full_width ? 4 : 2;
1153
1154 /* 8 banks */
1155 return (1ULL << (para->cols + para->rows + 3)) * width * para->ranks;
1156}
1157
1158unsigned long sunxi_dram_init(void)
1159{
Jernej Skrabece04cd492022-01-30 15:27:13 +01001160 struct sunxi_prcm_reg *const prcm =
1161 (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001162 struct dram_para para = {
1163 .clk = CONFIG_DRAM_CLK,
1164 .type = SUNXI_DRAM_TYPE_DDR3,
Jernej Skrabecdd533da2023-04-10 10:21:12 +02001165 .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
1166 .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
1167 .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
Jernej Skrabec63ab9552023-04-10 10:21:16 +02001168 .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
Jernej Skrabec9ec04b02023-04-10 10:21:17 +02001169 .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
Jernej Skrabecac8154d2023-04-10 10:21:19 +02001170 .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001171 .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
Jernej Skrabec63ab9552023-04-10 10:21:16 +02001172 .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
1173 .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001174 };
1175 unsigned long size;
1176
Jernej Skrabece04cd492022-01-30 15:27:13 +01001177 setbits_le32(&prcm->res_cal_ctrl, BIT(8));
1178 clrbits_le32(&prcm->ohms240, 0x3f);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001179
1180 mctl_auto_detect_rank_width(&para);
1181 mctl_auto_detect_dram_size(&para);
1182
1183 mctl_core_init(&para);
1184
1185 size = mctl_calc_size(&para);
1186
1187 mctl_set_master_priority();
1188
1189 return size;
1190};