blob: e62d5711d0f681a272b9970b3a6a150eca456811 [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.
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03009 * This driver supports DDR3, LPDDR3 and LPDDR4 memory. There is no
10 * DDR4 support yet.
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010011 *
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>
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010025
26enum {
27 MBUS_QOS_LOWEST = 0,
28 MBUS_QOS_LOW,
29 MBUS_QOS_HIGH,
30 MBUS_QOS_HIGHEST
31};
32
Andre Przywara16f6f792023-06-07 01:07:41 +010033static void mbus_configure_port(u8 port,
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010034 bool bwlimit,
35 bool priority,
36 u8 qos,
37 u8 waittime,
38 u8 acs,
39 u16 bwl0,
40 u16 bwl1,
41 u16 bwl2)
42{
43 struct sunxi_mctl_com_reg * const mctl_com =
44 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
45
46 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
47 | (priority ? (1 << 1) : 0)
48 | ((qos & 0x3) << 2)
49 | ((waittime & 0xf) << 4)
50 | ((acs & 0xff) << 8)
51 | (bwl0 << 16) );
52 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
53
54 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
55 writel_relaxed(cfg0, &mctl_com->master[port].cfg0);
56 writel_relaxed(cfg1, &mctl_com->master[port].cfg1);
57}
58
59#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
60 mbus_configure_port(port, bwlimit, false, \
61 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
62
63static void mctl_set_master_priority(void)
64{
65 struct sunxi_mctl_com_reg * const mctl_com =
66 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
67
68 /* enable bandwidth limit windows and set windows size 1us */
69 writel(399, &mctl_com->tmr);
70 writel(BIT(16), &mctl_com->bwcr);
71
72 MBUS_CONF( 0, true, HIGHEST, 0, 256, 128, 100);
73 MBUS_CONF( 1, true, HIGH, 0, 1536, 1400, 256);
74 MBUS_CONF( 2, true, HIGHEST, 0, 512, 256, 96);
75 MBUS_CONF( 3, true, HIGH, 0, 256, 100, 80);
76 MBUS_CONF( 4, true, HIGH, 2, 8192, 5500, 5000);
77 MBUS_CONF( 5, true, HIGH, 2, 100, 64, 32);
78 MBUS_CONF( 6, true, HIGH, 2, 100, 64, 32);
79 MBUS_CONF( 8, true, HIGH, 0, 256, 128, 64);
80 MBUS_CONF(11, true, HIGH, 0, 256, 128, 100);
81 MBUS_CONF(14, true, HIGH, 0, 1024, 256, 64);
82 MBUS_CONF(16, true, HIGHEST, 6, 8192, 2800, 2400);
83 MBUS_CONF(21, true, HIGHEST, 6, 2048, 768, 512);
84 MBUS_CONF(25, true, HIGHEST, 0, 100, 64, 32);
85 MBUS_CONF(26, true, HIGH, 2, 8192, 5500, 5000);
86 MBUS_CONF(37, true, HIGH, 0, 256, 128, 64);
87 MBUS_CONF(38, true, HIGH, 2, 100, 64, 32);
88 MBUS_CONF(39, true, HIGH, 2, 8192, 5500, 5000);
89 MBUS_CONF(40, true, HIGH, 2, 100, 64, 32);
90
91 dmb();
92}
93
Andre Przywaraa21a22c2023-06-07 01:07:42 +010094static void mctl_sys_init(u32 clk_rate)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010095{
96 struct sunxi_ccm_reg * const ccm =
97 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
98 struct sunxi_mctl_com_reg * const mctl_com =
99 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
100 struct sunxi_mctl_ctl_reg * const mctl_ctl =
101 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
102
103 /* Put all DRAM-related blocks to reset state */
104 clrbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
105 clrbits_le32(&ccm->mbus_cfg, MBUS_RESET);
106 clrbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
107 udelay(5);
108 clrbits_le32(&ccm->dram_gate_reset, BIT(RESET_SHIFT));
109 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
110 clrbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
111
112 udelay(5);
113
114 /* Set PLL5 rate to doubled DRAM clock rate */
115 writel(CCM_PLL5_CTRL_EN | CCM_PLL5_LOCK_EN | CCM_PLL5_OUT_EN |
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100116 CCM_PLL5_CTRL_N(clk_rate * 2 / 24), &ccm->pll5_cfg);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100117 mctl_await_completion(&ccm->pll5_cfg, CCM_PLL5_LOCK, CCM_PLL5_LOCK);
118
119 /* Configure DRAM mod clock */
120 writel(DRAM_CLK_SRC_PLL5, &ccm->dram_clk_cfg);
121 writel(BIT(RESET_SHIFT), &ccm->dram_gate_reset);
122 udelay(5);
123 setbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
124
125 /* Disable all channels */
126 writel(0, &mctl_com->maer0);
127 writel(0, &mctl_com->maer1);
128 writel(0, &mctl_com->maer2);
129
130 /* Configure MBUS and enable DRAM mod reset */
131 setbits_le32(&ccm->mbus_cfg, MBUS_RESET);
132 setbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
133
134 clrbits_le32(&mctl_com->unk_0x500, BIT(25));
135
136 setbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
137 udelay(5);
138
139 /* Unknown hack, which enables access of mctl_ctl regs */
140 writel(0x8000, &mctl_ctl->clken);
141}
142
Andre Przywara161812c2023-06-07 01:07:43 +0100143static void mctl_set_addrmap(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100144{
145 struct sunxi_mctl_ctl_reg * const mctl_ctl =
146 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +0100147 u8 cols = config->cols;
148 u8 rows = config->rows;
149 u8 ranks = config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100150
Andre Przywara161812c2023-06-07 01:07:43 +0100151 if (!config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100152 cols -= 1;
153
154 /* Ranks */
155 if (ranks == 2)
156 mctl_ctl->addrmap[0] = rows + cols - 3;
157 else
158 mctl_ctl->addrmap[0] = 0x1F;
159
160 /* Banks, hardcoded to 8 banks now */
161 mctl_ctl->addrmap[1] = (cols - 2) | (cols - 2) << 8 | (cols - 2) << 16;
162
163 /* Columns */
164 mctl_ctl->addrmap[2] = 0;
165 switch (cols) {
166 case 7:
167 mctl_ctl->addrmap[3] = 0x1F1F1F00;
168 mctl_ctl->addrmap[4] = 0x1F1F;
169 break;
170 case 8:
171 mctl_ctl->addrmap[3] = 0x1F1F0000;
172 mctl_ctl->addrmap[4] = 0x1F1F;
173 break;
174 case 9:
175 mctl_ctl->addrmap[3] = 0x1F000000;
176 mctl_ctl->addrmap[4] = 0x1F1F;
177 break;
178 case 10:
179 mctl_ctl->addrmap[3] = 0;
180 mctl_ctl->addrmap[4] = 0x1F1F;
181 break;
182 case 11:
183 mctl_ctl->addrmap[3] = 0;
184 mctl_ctl->addrmap[4] = 0x1F00;
185 break;
186 case 12:
187 mctl_ctl->addrmap[3] = 0;
188 mctl_ctl->addrmap[4] = 0;
189 break;
190 default:
191 panic("Unsupported DRAM configuration: column number invalid\n");
192 }
193
194 /* Rows */
195 mctl_ctl->addrmap[5] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
196 switch (rows) {
197 case 13:
198 mctl_ctl->addrmap[6] = (cols - 3) | 0x0F0F0F00;
199 mctl_ctl->addrmap[7] = 0x0F0F;
200 break;
201 case 14:
202 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | 0x0F0F0000;
203 mctl_ctl->addrmap[7] = 0x0F0F;
204 break;
205 case 15:
206 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | 0x0F000000;
207 mctl_ctl->addrmap[7] = 0x0F0F;
208 break;
209 case 16:
210 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
211 mctl_ctl->addrmap[7] = 0x0F0F;
212 break;
213 case 17:
214 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
215 mctl_ctl->addrmap[7] = (cols - 3) | 0x0F00;
216 break;
217 case 18:
218 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
219 mctl_ctl->addrmap[7] = (cols - 3) | ((cols - 3) << 8);
220 break;
221 default:
222 panic("Unsupported DRAM configuration: row number invalid\n");
223 }
224
225 /* Bank groups, DDR4 only */
226 mctl_ctl->addrmap[8] = 0x3F3F;
227}
228
229static const u8 phy_init[] = {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100230#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100231 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
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100235#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
236 0x18, 0x06, 0x00, 0x05, 0x04, 0x03, 0x09, 0x02,
237 0x08, 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
238 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07,
239 0x17, 0x19, 0x1a
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300240#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
241 0x02, 0x00, 0x17, 0x05, 0x04, 0x19, 0x06, 0x07,
242 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
243 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x01,
244 0x18, 0x03, 0x1a
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100245#endif
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100246};
247
Andre Przywara1af6f152023-09-07 20:38:46 +0100248#define MASK_BYTE(reg, nr) (((reg) >> ((nr) * 8)) & 0x1f)
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100249static void mctl_phy_configure_odt(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100250{
Andre Przywara1af6f152023-09-07 20:38:46 +0100251 uint32_t val_lo, val_hi;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100252
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300253 /*
254 * This part should be applicable to all memory types, but is
255 * usually found in LPDDR4 bootloaders. Therefore, we will leave
256 * only for this type of memory.
257 */
258 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
259 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x390, BIT(5), BIT(4));
260 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3d0, BIT(5), BIT(4));
261 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x410, BIT(5), BIT(4));
262 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x450, BIT(5), BIT(4));
263 }
264
Andre Przywara1af6f152023-09-07 20:38:46 +0100265 val_lo = para->dx_dri;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300266 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0x04040404 : para->dx_dri;
Andre Przywara1af6f152023-09-07 20:38:46 +0100267 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x388);
268 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x38c);
269 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c8);
270 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3cc);
271 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x408);
272 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x40c);
273 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x448);
274 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x44c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100275
Andre Przywara1af6f152023-09-07 20:38:46 +0100276 val_lo = para->ca_dri;
277 val_hi = para->ca_dri;
278 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x340);
279 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x344);
280 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x348);
281 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x34c);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200282
Andre Przywara1af6f152023-09-07 20:38:46 +0100283 val_lo = (para->type == SUNXI_DRAM_TYPE_LPDDR3) ? 0 : para->dx_odt;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300284 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0 : para->dx_odt;
Andre Przywara1af6f152023-09-07 20:38:46 +0100285 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x380);
286 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x384);
287 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c0);
288 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3c4);
289 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x400);
290 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x404);
291 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x440);
292 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x444);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100293
294 dmb();
295}
296
Andre Przywara161812c2023-06-07 01:07:43 +0100297static bool mctl_phy_write_leveling(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100298{
299 bool result = true;
300 u32 val;
301
302 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x80);
303 writel(4, SUNXI_DRAM_PHY0_BASE + 0xc);
304 writel(0x40, SUNXI_DRAM_PHY0_BASE + 0x10);
305
306 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
307
Andre Przywara161812c2023-06-07 01:07:43 +0100308 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100309 val = 0xf;
310 else
311 val = 3;
312
Jernej Skrabec5a088482023-04-10 10:21:11 +0200313 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100314
315 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
316
317 val = readl(SUNXI_DRAM_PHY0_BASE + 0x258);
318 if (val == 0 || val == 0x3f)
319 result = false;
320 val = readl(SUNXI_DRAM_PHY0_BASE + 0x25c);
321 if (val == 0 || val == 0x3f)
322 result = false;
323 val = readl(SUNXI_DRAM_PHY0_BASE + 0x318);
324 if (val == 0 || val == 0x3f)
325 result = false;
326 val = readl(SUNXI_DRAM_PHY0_BASE + 0x31c);
327 if (val == 0 || val == 0x3f)
328 result = false;
329
330 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
331
Andre Przywara161812c2023-06-07 01:07:43 +0100332 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100333 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
334
335 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
336
Andre Przywara161812c2023-06-07 01:07:43 +0100337 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100338 val = 0xf;
339 else
340 val = 3;
341
Jernej Skrabec5a088482023-04-10 10:21:11 +0200342 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100343
344 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
345 }
346
347 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
348
349 return result;
350}
351
Andre Przywara161812c2023-06-07 01:07:43 +0100352static bool mctl_phy_read_calibration(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100353{
354 bool result = true;
355 u32 val, tmp;
356
357 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
358
359 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
360
Andre Przywara161812c2023-06-07 01:07:43 +0100361 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100362 val = 0xf;
363 else
364 val = 3;
365
366 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
367 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
368 result = false;
369 break;
370 }
371 }
372
373 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
374
375 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
376
Andre Przywara161812c2023-06-07 01:07:43 +0100377 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100378 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
379
380 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
381
382 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
383 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
384 result = false;
385 break;
386 }
387 }
388
Jernej Skrabec4e048422022-01-29 16:58:43 +0100389 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100390 }
391
392 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
393
394 val = readl(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
395 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
396 if (val < tmp)
397 val = tmp;
398 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
399 if (val < tmp)
400 val = tmp;
401 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
402 if (val < tmp)
403 val = tmp;
404 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
405
406 setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
407
408 return result;
409}
410
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300411static bool mctl_phy_read_training(const struct dram_para *para,
412 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100413{
414 u32 val1, val2, *ptr1, *ptr2;
415 bool result = true;
416 int i;
417
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300418 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
419 writel(0, SUNXI_DRAM_PHY0_BASE + 0x800);
420 writel(0, SUNXI_DRAM_PHY0_BASE + 0x81c);
421 }
422
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100423 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
424 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x804, 0x3f, 0xf);
425 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x808, 0x3f, 0xf);
426 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa04, 0x3f, 0xf);
427 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa08, 0x3f, 0xf);
428
429 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
430 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
431
Jernej Skrabec5a088482023-04-10 10:21:11 +0200432 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100433 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
434 result = false;
435
Andre Przywara161812c2023-06-07 01:07:43 +0100436 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200437 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100438 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
439 result = false;
440 }
441
Jernej Skrabec5a088482023-04-10 10:21:11 +0200442 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x898);
443 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x850);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100444 for (i = 0; i < 9; i++) {
445 val1 = readl(&ptr1[i]);
446 val2 = readl(&ptr2[i]);
447 if (val1 - val2 <= 6)
448 result = false;
449 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200450 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
451 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x874);
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
Andre Przywara161812c2023-06-07 01:07:43 +0100459 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200460 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
461 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100462 for (i = 0; i < 9; i++) {
463 val1 = readl(&ptr1[i]);
464 val2 = readl(&ptr2[i]);
465 if (val1 - val2 <= 6)
466 result = false;
467 }
468
Jernej Skrabec5a088482023-04-10 10:21:11 +0200469 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xabc);
470 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100471 for (i = 0; i < 9; i++) {
472 val1 = readl(&ptr1[i]);
473 val2 = readl(&ptr2[i]);
474 if (val1 - val2 <= 6)
475 result = false;
476 }
477 }
478
479 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
480
Andre Przywara161812c2023-06-07 01:07:43 +0100481 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100482 /* maybe last parameter should be 1? */
483 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
484
485 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
486 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
487
Jernej Skrabec5a088482023-04-10 10:21:11 +0200488 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100489 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
490 result = false;
491
Andre Przywara161812c2023-06-07 01:07:43 +0100492 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200493 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100494 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
495 result = false;
496 }
497
498 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
499 }
500
501 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3);
502
503 return result;
504}
505
Andre Przywara161812c2023-06-07 01:07:43 +0100506static bool mctl_phy_write_training(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100507{
508 u32 val1, val2, *ptr1, *ptr2;
509 bool result = true;
510 int i;
511
512 writel(0, SUNXI_DRAM_PHY0_BASE + 0x134);
513 writel(0, SUNXI_DRAM_PHY0_BASE + 0x138);
514 writel(0, SUNXI_DRAM_PHY0_BASE + 0x19c);
515 writel(0, SUNXI_DRAM_PHY0_BASE + 0x1a0);
516
517 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 8);
518
519 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
520 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
521
Jernej Skrabec5a088482023-04-10 10:21:11 +0200522 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100523 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
524 result = false;
525
Andre Przywara161812c2023-06-07 01:07:43 +0100526 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200527 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100528 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
529 result = false;
530 }
531
Jernej Skrabec5a088482023-04-10 10:21:11 +0200532 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x938);
533 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100534 for (i = 0; i < 9; i++) {
535 val1 = readl(&ptr1[i]);
536 val2 = readl(&ptr2[i]);
537 if (val1 - val2 <= 6)
538 result = false;
539 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200540 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x95c);
541 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x914);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100542 for (i = 0; i < 9; i++) {
543 val1 = readl(&ptr1[i]);
544 val2 = readl(&ptr2[i]);
545 if (val1 - val2 <= 6)
546 result = false;
547 }
548
Andre Przywara161812c2023-06-07 01:07:43 +0100549 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200550 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
551 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100552 for (i = 0; i < 9; i++) {
553 val1 = readl(&ptr1[i]);
554 val2 = readl(&ptr2[i]);
555 if (val1 - val2 <= 6)
556 result = false;
557 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200558 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
559 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100560 for (i = 0; i < 9; i++) {
561 val1 = readl(&ptr1[i]);
562 val2 = readl(&ptr2[i]);
563 if (val1 - val2 <= 6)
564 result = false;
565 }
566 }
567
568 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
569
Andre Przywara161812c2023-06-07 01:07:43 +0100570 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100571 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
572
573 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
574 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
575
Jernej Skrabec5a088482023-04-10 10:21:11 +0200576 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100577 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
578 result = false;
579
Andre Przywara161812c2023-06-07 01:07:43 +0100580 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200581 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100582 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
583 result = false;
584 }
585
586 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
587 }
588
589 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc);
590
591 return result;
592}
593
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100594static void mctl_phy_bit_delay_compensation(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100595{
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200596 u32 *ptr, val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100597 int i;
598
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200599 if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
600 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
601 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
602 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300603 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
604 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4, 0x80);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100605
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200606 if (para->tpr10 & BIT(30))
607 val = para->tpr11 & 0x3f;
608 else
609 val = (para->tpr11 & 0xf) << 1;
610
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200611 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484);
612 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200613 writel_relaxed(val, ptr);
614 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200615 ptr += 2;
616 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200617
618 if (para->tpr10 & BIT(30))
619 val = (para->odt_en >> 15) & 0x1e;
620 else
621 val = (para->tpr11 >> 15) & 0x1e;
622
623 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4d0);
624 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x590);
625 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4cc);
626 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x58c);
627
628 if (para->tpr10 & BIT(30))
629 val = (para->tpr11 >> 8) & 0x3f;
630 else
631 val = (para->tpr11 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100632
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200633 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
634 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200635 writel_relaxed(val, ptr);
636 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200637 ptr += 2;
638 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200639
640 if (para->tpr10 & BIT(30))
641 val = (para->odt_en >> 19) & 0x1e;
642 else
643 val = (para->tpr11 >> 19) & 0x1e;
644
645 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x524);
646 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e4);
647 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x520);
648 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e0);
649
650 if (para->tpr10 & BIT(30))
651 val = (para->tpr11 >> 16) & 0x3f;
652 else
653 val = (para->tpr11 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100654
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200655 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604);
656 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200657 writel_relaxed(val, ptr);
658 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200659 ptr += 2;
660 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200661
662 if (para->tpr10 & BIT(30))
663 val = (para->odt_en >> 23) & 0x1e;
664 else
665 val = (para->tpr11 >> 23) & 0x1e;
666
667 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x650);
668 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x710);
669 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x64c);
670 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x70c);
671
672 if (para->tpr10 & BIT(30))
673 val = (para->tpr11 >> 24) & 0x3f;
674 else
675 val = (para->tpr11 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100676
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200677 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658);
678 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200679 writel_relaxed(val, ptr);
680 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200681 ptr += 2;
682 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200683
684 if (para->tpr10 & BIT(30))
685 val = (para->odt_en >> 27) & 0x1e;
686 else
687 val = (para->tpr11 >> 27) & 0x1e;
688
689 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a4);
690 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x764);
691 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a0);
692 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x760);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100693
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200694 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100695
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200696 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
697 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100698
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200699 if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
700 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
701 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100702
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200703 if (para->tpr10 & BIT(30))
704 val = para->tpr12 & 0x3f;
705 else
706 val = (para->tpr12 & 0xf) << 1;
707
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200708 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480);
709 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200710 writel_relaxed(val, ptr);
711 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200712 ptr += 2;
713 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200714
715 if (para->tpr10 & BIT(30))
716 val = (para->odt_en << 1) & 0x1e;
717 else
718 val = (para->tpr12 >> 15) & 0x1e;
719
720 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x528);
721 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e8);
722 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4c8);
723 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x588);
724
725 if (para->tpr10 & BIT(30))
726 val = (para->tpr12 >> 8) & 0x3f;
727 else
728 val = (para->tpr12 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100729
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200730 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
731 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200732 writel_relaxed(val, ptr);
733 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200734 ptr += 2;
735 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200736
737 if (para->tpr10 & BIT(30))
738 val = (para->odt_en >> 3) & 0x1e;
739 else
740 val = (para->tpr12 >> 19) & 0x1e;
741
742 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x52c);
743 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5ec);
744 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x51c);
745 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5dc);
746
747 if (para->tpr10 & BIT(30))
748 val = (para->tpr12 >> 16) & 0x3f;
749 else
750 val = (para->tpr12 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100751
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200752 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600);
753 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200754 writel_relaxed(val, ptr);
755 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200756 ptr += 2;
757 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200758
759 if (para->tpr10 & BIT(30))
760 val = (para->odt_en >> 7) & 0x1e;
761 else
762 val = (para->tpr12 >> 23) & 0x1e;
763
764 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a8);
765 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x768);
766 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x648);
767 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x708);
768
769 if (para->tpr10 & BIT(30))
770 val = (para->tpr12 >> 24) & 0x3f;
771 else
772 val = (para->tpr12 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100773
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200774 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
775 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200776 writel_relaxed(val, ptr);
777 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200778 ptr += 2;
779 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200780
781 if (para->tpr10 & BIT(30))
782 val = (para->odt_en >> 11) & 0x1e;
783 else
784 val = (para->tpr12 >> 27) & 0x1e;
785
786 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6ac);
787 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x76c);
788 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x69c);
789 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x75c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100790
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200791 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100792
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200793 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
794 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100795}
796
Andre Przywara161812c2023-06-07 01:07:43 +0100797static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para,
798 const struct dram_config *config)
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200799{
800 u32 val, *ptr;
801 int i;
802
803 if (para->tpr0 & BIT(30))
804 val = (para->tpr0 >> 7) & 0x3e;
805 else
806 val = (para->tpr10 >> 3) & 0x1e;
807
808 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
809 for (i = 0; i < 32; i++)
810 writel(val, &ptr[i]);
811
812 val = (para->tpr10 << 1) & 0x1e;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200813 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200814 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
815 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200816 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200817
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300818 val = (para->tpr10 >> 7) & 0x1e;
819 switch (para->type) {
820 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100821 if (para->tpr2 & 1) {
822 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
823 if (config->ranks == 2) {
824 val = (para->tpr10 >> 11) & 0x1e;
825 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
826 }
827 if (para->tpr0 & BIT(31)) {
828 val = (para->tpr0 << 1) & 0x3e;
829 writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
830 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
831 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
832 }
833 } else {
834 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
835 if (config->ranks == 2) {
836 val = (para->tpr10 >> 11) & 0x1e;
837 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
838 }
839 if (para->tpr0 & BIT(31)) {
840 val = (para->tpr0 << 1) & 0x3e;
841 writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
842 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
843 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
844 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200845 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300846 break;
847 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100848 if (para->tpr2 & 1) {
849 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a0);
850 if (config->ranks == 2) {
851 val = (para->tpr10 >> 11) & 0x1e;
852 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
853 }
854 } else {
855 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e8);
856 if (config->ranks == 2) {
857 val = (para->tpr10 >> 11) & 0x1e;
858 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f8);
859 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200860 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300861 break;
862 case SUNXI_DRAM_TYPE_LPDDR4:
863 if (para->tpr2 & 1) {
864 writel(val, SUNXI_DRAM_PHY0_BASE + 0x788);
865 } else {
866 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
867 };
868 break;
869 case SUNXI_DRAM_TYPE_DDR4:
870 default:
871 panic("This DRAM setup is currently not supported.\n");
872 };
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200873}
874
Andre Przywara161812c2023-06-07 01:07:43 +0100875static bool mctl_phy_init(const struct dram_para *para,
876 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100877{
878 struct sunxi_mctl_com_reg * const mctl_com =
879 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
880 struct sunxi_mctl_ctl_reg * const mctl_ctl =
881 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200882 u32 val, val2, *ptr, mr0, mr2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100883 int i;
884
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300885 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
886 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4,0x80);
887
Andre Przywara161812c2023-06-07 01:07:43 +0100888 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100889 val = 0xf;
890 else
891 val = 3;
892 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
893
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300894 switch (para->type) {
895 case SUNXI_DRAM_TYPE_DDR3:
896 if (para->tpr2 & 0x100) {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100897 val = 9;
898 val2 = 7;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300899 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100900 val = 13;
901 val2 = 9;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300902 }
903 break;
904 case SUNXI_DRAM_TYPE_LPDDR3:
905 if (para->tpr2 & 0x100) {
906 val = 12;
907 val2 = 6;
908 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100909 val = 14;
910 val2 = 8;
911 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300912 break;
913 case SUNXI_DRAM_TYPE_LPDDR4:
914 val = 20;
915 val2 = 10;
916 break;
917 case SUNXI_DRAM_TYPE_DDR4:
918 default:
919 panic("This DRAM setup is currently not supported.\n");
920 };
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200921
922 writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
923 writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
924 writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
925 writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100926
927 writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
928 writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
929 writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
930 writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
931
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200932 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
933 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
934 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
935 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100936
Jernej Skrabec5a088482023-04-10 10:21:11 +0200937 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100938 for (i = 0; i < ARRAY_SIZE(phy_init); i++)
939 writel(phy_init[i], &ptr[i]);
940
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200941 if (para->tpr10 & TPR10_CA_BIT_DELAY)
Andre Przywara161812c2023-06-07 01:07:43 +0100942 mctl_phy_ca_bit_delay_compensation(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100943
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300944 switch (para->type) {
945 case SUNXI_DRAM_TYPE_DDR3:
946 val = para->tpr6 & 0xff;
947 break;
948 case SUNXI_DRAM_TYPE_LPDDR3:
949 val = para->tpr6 >> 8 & 0xff;
950 break;
951 case SUNXI_DRAM_TYPE_LPDDR4:
952 val = para->tpr6 >> 24 & 0xff;
953 break;
954 case SUNXI_DRAM_TYPE_DDR4:
955 default:
956 panic("This DRAM setup is currently not supported.\n");
957 };
958
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100959 writel(val, SUNXI_DRAM_PHY0_BASE + 0x3dc);
960 writel(val, SUNXI_DRAM_PHY0_BASE + 0x45c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100961
Jernej Skrabec64712da2023-04-10 10:21:14 +0200962 mctl_phy_configure_odt(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100963
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300964 switch (para->type) {
965 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100966 val = 0x0a;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300967 break;
968 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100969 val = 0x0b;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300970 break;
971 case SUNXI_DRAM_TYPE_LPDDR4:
972 val = 0x0d;
973 break;
974 case SUNXI_DRAM_TYPE_DDR4:
975 default:
976 panic("This DRAM setup is currently not supported.\n");
977 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100978 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x7, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100979
980 if (para->clk <= 672)
981 writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
982 if (para->clk > 500) {
983 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
984 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
985 } else {
986 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
987 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
988 }
989
990 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
991
Jernej Skrabec5a088482023-04-10 10:21:11 +0200992 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100993
994 writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
995 clrbits_le32(&mctl_com->unk_0x500, 0x200);
996
997 writel(0, &mctl_ctl->swctl);
998 setbits_le32(&mctl_ctl->dfimisc, 1);
999
1000 /* start DFI init */
1001 setbits_le32(&mctl_ctl->dfimisc, 0x20);
1002 writel(1, &mctl_ctl->swctl);
1003 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1004 /* poll DFI init complete */
1005 mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
1006 writel(0, &mctl_ctl->swctl);
1007 clrbits_le32(&mctl_ctl->dfimisc, 0x20);
1008
1009 clrbits_le32(&mctl_ctl->pwrctl, 0x20);
1010 writel(1, &mctl_ctl->swctl);
1011 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1012 mctl_await_completion(&mctl_ctl->statr, 3, 1);
1013
1014 writel(0, &mctl_ctl->swctl);
1015 clrbits_le32(&mctl_ctl->dfimisc, 1);
1016
1017 writel(1, &mctl_ctl->swctl);
1018 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1019
Jernej Skrabecac8154d2023-04-10 10:21:19 +02001020 if (para->tpr2 & 0x100) {
1021 mr0 = 0x1b50;
1022 mr2 = 0x10;
1023 } else {
1024 mr0 = 0x1f14;
1025 mr2 = 0x20;
1026 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001027 switch (para->type) {
1028 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001029 writel(mr0, &mctl_ctl->mrctrl1);
1030 writel(0x80000030, &mctl_ctl->mrctrl0);
1031 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001032
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001033 writel(4, &mctl_ctl->mrctrl1);
1034 writel(0x80001030, &mctl_ctl->mrctrl0);
1035 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001036
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001037 writel(mr2, &mctl_ctl->mrctrl1);
1038 writel(0x80002030, &mctl_ctl->mrctrl0);
1039 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001040
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001041 writel(0, &mctl_ctl->mrctrl1);
1042 writel(0x80003030, &mctl_ctl->mrctrl0);
1043 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001044 break;
1045 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001046 writel(mr0, &mctl_ctl->mrctrl1);
1047 writel(0x800000f0, &mctl_ctl->mrctrl0);
1048 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1049
1050 writel(4, &mctl_ctl->mrctrl1);
1051 writel(0x800000f0, &mctl_ctl->mrctrl0);
1052 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1053
1054 writel(mr2, &mctl_ctl->mrctrl1);
1055 writel(0x800000f0, &mctl_ctl->mrctrl0);
1056 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1057
1058 writel(0x301, &mctl_ctl->mrctrl1);
1059 writel(0x800000f0, &mctl_ctl->mrctrl0);
1060 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001061 break;
1062 case SUNXI_DRAM_TYPE_LPDDR4:
1063 writel(0x0, &mctl_ctl->mrctrl1);
1064 writel(0x80000030, &mctl_ctl->mrctrl0);
1065 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1066
1067 writel(0x134, &mctl_ctl->mrctrl1);
1068 writel(0x80000030, &mctl_ctl->mrctrl0);
1069 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1070
1071 writel(0x21b, &mctl_ctl->mrctrl1);
1072 writel(0x80000030, &mctl_ctl->mrctrl0);
1073 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1074
1075 writel(0x333, &mctl_ctl->mrctrl1);
1076 writel(0x80000030, &mctl_ctl->mrctrl0);
1077 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1078
1079 writel(0x403, &mctl_ctl->mrctrl1);
1080 writel(0x80000030, &mctl_ctl->mrctrl0);
1081 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1082
1083 writel(0xb04, &mctl_ctl->mrctrl1);
1084 writel(0x80000030, &mctl_ctl->mrctrl0);
1085 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1086
1087 writel(0xc72, &mctl_ctl->mrctrl1);
1088 writel(0x80000030, &mctl_ctl->mrctrl0);
1089 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1090
1091 writel(0xe09, &mctl_ctl->mrctrl1);
1092 writel(0x80000030, &mctl_ctl->mrctrl0);
1093 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1094
1095 writel(0x1624, &mctl_ctl->mrctrl1);
1096 writel(0x80000030, &mctl_ctl->mrctrl0);
1097 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1098 break;
1099 case SUNXI_DRAM_TYPE_DDR4:
1100 default:
1101 panic("This DRAM setup is currently not supported.\n");
1102 };
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001103
1104 writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
1105
1106 writel(0, &mctl_ctl->swctl);
1107 clrbits_le32(&mctl_ctl->rfshctl3, 1);
1108 writel(1, &mctl_ctl->swctl);
1109
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001110 if (para->tpr10 & TPR10_WRITE_LEVELING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001111 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001112 if (mctl_phy_write_leveling(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001113 break;
1114 if (i == 5) {
1115 debug("write leveling failed!\n");
1116 return false;
1117 }
1118 }
1119
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001120 if (para->tpr10 & TPR10_READ_CALIBRATION) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001121 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001122 if (mctl_phy_read_calibration(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001123 break;
1124 if (i == 5) {
1125 debug("read calibration failed!\n");
1126 return false;
1127 }
1128 }
1129
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001130 if (para->tpr10 & TPR10_READ_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001131 for (i = 0; i < 5; i++)
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001132 if (mctl_phy_read_training(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001133 break;
1134 if (i == 5) {
1135 debug("read training failed!\n");
1136 return false;
1137 }
1138 }
1139
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001140 if (para->tpr10 & TPR10_WRITE_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001141 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001142 if (mctl_phy_write_training(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001143 break;
1144 if (i == 5) {
1145 debug("write training failed!\n");
1146 return false;
1147 }
1148 }
1149
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001150 mctl_phy_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001151
1152 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
1153
1154 return true;
1155}
1156
Andre Przywara161812c2023-06-07 01:07:43 +01001157static bool mctl_ctrl_init(const struct dram_para *para,
1158 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001159{
1160 struct sunxi_mctl_com_reg * const mctl_com =
1161 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
1162 struct sunxi_mctl_ctl_reg * const mctl_ctl =
1163 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
1164 u32 reg_val;
1165
1166 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
1167 writel(0x8000, &mctl_ctl->clken);
1168
1169 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1170
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001171 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
1172 writel(1, SUNXI_DRAM_COM_BASE + 0x50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001173 clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
1174
1175 writel(0, &mctl_ctl->hwlpctl);
1176
1177 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1178
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001179 reg_val = MSTR_ACTIVE_RANKS(config->ranks);
1180 switch (para->type) {
1181 case SUNXI_DRAM_TYPE_DDR3:
1182 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
1183 break;
1184 case SUNXI_DRAM_TYPE_LPDDR3:
1185 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_LPDDR3;
1186 break;
1187 case SUNXI_DRAM_TYPE_LPDDR4:
1188 reg_val |= MSTR_BURST_LENGTH(16) | MSTR_DEVICETYPE_LPDDR4;
1189 break;
1190 case SUNXI_DRAM_TYPE_DDR4:
1191 default:
1192 panic("This DRAM setup is currently not supported.\n");
1193 };
Andre Przywara161812c2023-06-07 01:07:43 +01001194 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001195 reg_val |= MSTR_BUSWIDTH_FULL;
1196 else
1197 reg_val |= MSTR_BUSWIDTH_HALF;
1198 writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
1199
Andre Przywara161812c2023-06-07 01:07:43 +01001200 if (config->ranks == 2)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001201 writel(0x0303, &mctl_ctl->odtmap);
1202 else
1203 writel(0x0201, &mctl_ctl->odtmap);
1204
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001205 switch (para->type) {
1206 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001207 reg_val = 0x06000400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001208 break;
1209 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001210 reg_val = 0x09020400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001211 break;
1212 case SUNXI_DRAM_TYPE_LPDDR4:
1213 reg_val = 0x04000400;
1214 break;
1215 case SUNXI_DRAM_TYPE_DDR4:
1216 default:
1217 panic("This DRAM setup is currently not supported.\n");
1218 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001219 writel(reg_val, &mctl_ctl->odtcfg);
1220 writel(reg_val, &mctl_ctl->unk_0x2240);
1221 writel(reg_val, &mctl_ctl->unk_0x3240);
1222 writel(reg_val, &mctl_ctl->unk_0x4240);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001223
Jernej Skrabec472d4042023-04-10 10:21:10 +02001224 writel(BIT(31), &mctl_com->cr);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001225
Andre Przywara161812c2023-06-07 01:07:43 +01001226 mctl_set_addrmap(config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001227
1228 mctl_set_timing_params(para);
1229
1230 writel(0, &mctl_ctl->pwrctl);
1231
1232 setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
1233 setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
1234 setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
1235 setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
1236 setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
1237
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001238 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
1239 setbits_le32(&mctl_ctl->dbictl, 0x1);
1240
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001241 setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1242 clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
1243
1244 writel(0, &mctl_com->maer0);
1245 writel(0, &mctl_com->maer1);
1246 writel(0, &mctl_com->maer2);
1247
1248 writel(0x20, &mctl_ctl->pwrctl);
1249 setbits_le32(&mctl_ctl->clken, BIT(8));
1250
1251 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
1252 /* this write seems to enable PHY MMIO region */
1253 setbits_le32(&mctl_com->unk_0x500, BIT(24));
1254
Andre Przywara161812c2023-06-07 01:07:43 +01001255 if (!mctl_phy_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001256 return false;
1257
1258 writel(0, &mctl_ctl->swctl);
1259 clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1260
1261 setbits_le32(&mctl_com->unk_0x014, BIT(31));
1262 writel(0xffffffff, &mctl_com->maer0);
1263 writel(0x7ff, &mctl_com->maer1);
1264 writel(0xffff, &mctl_com->maer2);
1265
1266 writel(1, &mctl_ctl->swctl);
1267 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1268
1269 return true;
1270}
1271
Andre Przywara161812c2023-06-07 01:07:43 +01001272static bool mctl_core_init(const struct dram_para *para,
1273 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001274{
Andre Przywaraa21a22c2023-06-07 01:07:42 +01001275 mctl_sys_init(para->clk);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001276
Andre Przywara161812c2023-06-07 01:07:43 +01001277 return mctl_ctrl_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001278}
1279
Andre Przywara161812c2023-06-07 01:07:43 +01001280static void mctl_auto_detect_rank_width(const struct dram_para *para,
1281 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001282{
1283 /* this is minimum size that it's supported */
Andre Przywara161812c2023-06-07 01:07:43 +01001284 config->cols = 8;
1285 config->rows = 13;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001286
1287 /*
1288 * Strategy here is to test most demanding combination first and least
1289 * demanding last, otherwise HW might not be fully utilized. For
1290 * example, half bus width and rank = 1 combination would also work
1291 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
1292 * visible.
1293 */
1294
1295 debug("testing 32-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001296 config->bus_full_width = 1;
1297 config->ranks = 2;
1298 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001299 return;
1300
1301 debug("testing 32-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001302 config->bus_full_width = 1;
1303 config->ranks = 1;
1304 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001305 return;
1306
1307 debug("testing 16-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001308 config->bus_full_width = 0;
1309 config->ranks = 2;
1310 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001311 return;
1312
1313 debug("testing 16-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001314 config->bus_full_width = 0;
1315 config->ranks = 1;
1316 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001317 return;
1318
1319 panic("This DRAM setup is currently not supported.\n");
1320}
1321
Andre Przywara161812c2023-06-07 01:07:43 +01001322static void mctl_auto_detect_dram_size(const struct dram_para *para,
1323 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001324{
1325 /* detect row address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001326 config->cols = 8;
1327 config->rows = 18;
1328 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001329
Andre Przywara161812c2023-06-07 01:07:43 +01001330 for (config->rows = 13; config->rows < 18; config->rows++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001331 /* 8 banks, 8 bit per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001332 if (mctl_mem_matches((1 << (config->rows + config->cols +
1333 4 + config->bus_full_width))))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001334 break;
1335 }
1336
1337 /* detect column address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001338 config->cols = 11;
1339 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001340
Andre Przywara161812c2023-06-07 01:07:43 +01001341 for (config->cols = 8; config->cols < 11; config->cols++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001342 /* 8 bits per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001343 if (mctl_mem_matches(1 << (config->cols + 1 +
1344 config->bus_full_width)))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001345 break;
1346 }
1347}
1348
Andre Przywara161812c2023-06-07 01:07:43 +01001349static unsigned long mctl_calc_size(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001350{
Andre Przywara161812c2023-06-07 01:07:43 +01001351 u8 width = config->bus_full_width ? 4 : 2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001352
1353 /* 8 banks */
Andre Przywara161812c2023-06-07 01:07:43 +01001354 return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001355}
1356
Andre Przywara161812c2023-06-07 01:07:43 +01001357static const struct dram_para para = {
1358 .clk = CONFIG_DRAM_CLK,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001359#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Andre Przywara161812c2023-06-07 01:07:43 +01001360 .type = SUNXI_DRAM_TYPE_DDR3,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001361#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
1362 .type = SUNXI_DRAM_TYPE_LPDDR3,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001363#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
1364 .type = SUNXI_DRAM_TYPE_LPDDR4,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001365#endif
Andre Przywara161812c2023-06-07 01:07:43 +01001366 .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
1367 .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
1368 .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
1369 .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
1370 .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
1371 .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001372 .tpr6 = CONFIG_DRAM_SUN50I_H616_TPR6,
Andre Przywara161812c2023-06-07 01:07:43 +01001373 .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
1374 .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
1375 .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
1376};
1377
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001378unsigned long sunxi_dram_init(void)
1379{
Jernej Skrabece04cd492022-01-30 15:27:13 +01001380 struct sunxi_prcm_reg *const prcm =
1381 (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +01001382 struct dram_config config;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001383 unsigned long size;
1384
Jernej Skrabece04cd492022-01-30 15:27:13 +01001385 setbits_le32(&prcm->res_cal_ctrl, BIT(8));
1386 clrbits_le32(&prcm->ohms240, 0x3f);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001387
Andre Przywara161812c2023-06-07 01:07:43 +01001388 mctl_auto_detect_rank_width(&para, &config);
1389 mctl_auto_detect_dram_size(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001390
Andre Przywara161812c2023-06-07 01:07:43 +01001391 mctl_core_init(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001392
Andre Przywara161812c2023-06-07 01:07:43 +01001393 size = mctl_calc_size(&config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001394
1395 mctl_set_master_priority();
1396
1397 return size;
1398};