blob: c5c1331a4c3c33a5c4364616a4956b9bfc959611 [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>
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
Andre Przywara16f6f792023-06-07 01:07:41 +010034static void mbus_configure_port(u8 port,
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010035 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
Andre Przywaraa21a22c2023-06-07 01:07:42 +010095static void mctl_sys_init(u32 clk_rate)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010096{
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 Przywaraa21a22c2023-06-07 01:07:42 +0100117 CCM_PLL5_CTRL_N(clk_rate * 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
Andre Przywara161812c2023-06-07 01:07:43 +0100144static void mctl_set_addrmap(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100145{
146 struct sunxi_mctl_ctl_reg * const mctl_ctl =
147 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +0100148 u8 cols = config->cols;
149 u8 rows = config->rows;
150 u8 ranks = config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100151
Andre Przywara161812c2023-06-07 01:07:43 +0100152 if (!config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100153 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[] = {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100231#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100232 0x07, 0x0b, 0x02, 0x16, 0x0d, 0x0e, 0x14, 0x19,
233 0x0a, 0x15, 0x03, 0x13, 0x04, 0x0c, 0x10, 0x06,
234 0x0f, 0x11, 0x1a, 0x01, 0x12, 0x17, 0x00, 0x08,
235 0x09, 0x05, 0x18
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100236#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
237 0x18, 0x06, 0x00, 0x05, 0x04, 0x03, 0x09, 0x02,
238 0x08, 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
239 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07,
240 0x17, 0x19, 0x1a
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300241#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
242 0x02, 0x00, 0x17, 0x05, 0x04, 0x19, 0x06, 0x07,
243 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
244 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x01,
245 0x18, 0x03, 0x1a
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100246#endif
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100247};
248
Andre Przywara1af6f152023-09-07 20:38:46 +0100249#define MASK_BYTE(reg, nr) (((reg) >> ((nr) * 8)) & 0x1f)
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100250static void mctl_phy_configure_odt(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100251{
Andre Przywara1af6f152023-09-07 20:38:46 +0100252 uint32_t val_lo, val_hi;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100253
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300254 /*
255 * This part should be applicable to all memory types, but is
256 * usually found in LPDDR4 bootloaders. Therefore, we will leave
257 * only for this type of memory.
258 */
259 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
260 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x390, BIT(5), BIT(4));
261 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3d0, BIT(5), BIT(4));
262 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x410, BIT(5), BIT(4));
263 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x450, BIT(5), BIT(4));
264 }
265
Andre Przywara1af6f152023-09-07 20:38:46 +0100266 val_lo = para->dx_dri;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300267 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0x04040404 : para->dx_dri;
Andre Przywara1af6f152023-09-07 20:38:46 +0100268 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x388);
269 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x38c);
270 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c8);
271 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3cc);
272 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x408);
273 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x40c);
274 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x448);
275 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x44c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100276
Andre Przywara1af6f152023-09-07 20:38:46 +0100277 val_lo = para->ca_dri;
278 val_hi = para->ca_dri;
279 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x340);
280 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x344);
281 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x348);
282 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x34c);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200283
Andre Przywara1af6f152023-09-07 20:38:46 +0100284 val_lo = (para->type == SUNXI_DRAM_TYPE_LPDDR3) ? 0 : para->dx_odt;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300285 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0 : para->dx_odt;
Andre Przywara1af6f152023-09-07 20:38:46 +0100286 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x380);
287 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x384);
288 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c0);
289 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3c4);
290 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x400);
291 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x404);
292 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x440);
293 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x444);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100294
295 dmb();
296}
297
Andre Przywara161812c2023-06-07 01:07:43 +0100298static bool mctl_phy_write_leveling(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100299{
300 bool result = true;
301 u32 val;
302
303 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x80);
304 writel(4, SUNXI_DRAM_PHY0_BASE + 0xc);
305 writel(0x40, SUNXI_DRAM_PHY0_BASE + 0x10);
306
307 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
308
Andre Przywara161812c2023-06-07 01:07:43 +0100309 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100310 val = 0xf;
311 else
312 val = 3;
313
Jernej Skrabec5a088482023-04-10 10:21:11 +0200314 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100315
316 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
317
318 val = readl(SUNXI_DRAM_PHY0_BASE + 0x258);
319 if (val == 0 || val == 0x3f)
320 result = false;
321 val = readl(SUNXI_DRAM_PHY0_BASE + 0x25c);
322 if (val == 0 || val == 0x3f)
323 result = false;
324 val = readl(SUNXI_DRAM_PHY0_BASE + 0x318);
325 if (val == 0 || val == 0x3f)
326 result = false;
327 val = readl(SUNXI_DRAM_PHY0_BASE + 0x31c);
328 if (val == 0 || val == 0x3f)
329 result = false;
330
331 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
332
Andre Przywara161812c2023-06-07 01:07:43 +0100333 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100334 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
335
336 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
337
Andre Przywara161812c2023-06-07 01:07:43 +0100338 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100339 val = 0xf;
340 else
341 val = 3;
342
Jernej Skrabec5a088482023-04-10 10:21:11 +0200343 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100344
345 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
346 }
347
348 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
349
350 return result;
351}
352
Andre Przywara161812c2023-06-07 01:07:43 +0100353static bool mctl_phy_read_calibration(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100354{
355 bool result = true;
356 u32 val, tmp;
357
358 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
359
360 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
361
Andre Przywara161812c2023-06-07 01:07:43 +0100362 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100363 val = 0xf;
364 else
365 val = 3;
366
367 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
368 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
369 result = false;
370 break;
371 }
372 }
373
374 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
375
376 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
377
Andre Przywara161812c2023-06-07 01:07:43 +0100378 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100379 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
380
381 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
382
383 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
384 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
385 result = false;
386 break;
387 }
388 }
389
Jernej Skrabec4e048422022-01-29 16:58:43 +0100390 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100391 }
392
393 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
394
395 val = readl(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
396 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
397 if (val < tmp)
398 val = tmp;
399 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
400 if (val < tmp)
401 val = tmp;
402 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
403 if (val < tmp)
404 val = tmp;
405 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
406
407 setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
408
409 return result;
410}
411
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300412static bool mctl_phy_read_training(const struct dram_para *para,
413 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100414{
415 u32 val1, val2, *ptr1, *ptr2;
416 bool result = true;
417 int i;
418
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300419 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
420 writel(0, SUNXI_DRAM_PHY0_BASE + 0x800);
421 writel(0, SUNXI_DRAM_PHY0_BASE + 0x81c);
422 }
423
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100424 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
425 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x804, 0x3f, 0xf);
426 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x808, 0x3f, 0xf);
427 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa04, 0x3f, 0xf);
428 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa08, 0x3f, 0xf);
429
430 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
431 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
432
Jernej Skrabec5a088482023-04-10 10:21:11 +0200433 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100434 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
435 result = false;
436
Andre Przywara161812c2023-06-07 01:07:43 +0100437 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200438 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100439 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
440 result = false;
441 }
442
Jernej Skrabec5a088482023-04-10 10:21:11 +0200443 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x898);
444 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x850);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100445 for (i = 0; i < 9; i++) {
446 val1 = readl(&ptr1[i]);
447 val2 = readl(&ptr2[i]);
448 if (val1 - val2 <= 6)
449 result = false;
450 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200451 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
452 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x874);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100453 for (i = 0; i < 9; i++) {
454 val1 = readl(&ptr1[i]);
455 val2 = readl(&ptr2[i]);
456 if (val1 - val2 <= 6)
457 result = false;
458 }
459
Andre Przywara161812c2023-06-07 01:07:43 +0100460 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200461 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
462 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100463 for (i = 0; i < 9; i++) {
464 val1 = readl(&ptr1[i]);
465 val2 = readl(&ptr2[i]);
466 if (val1 - val2 <= 6)
467 result = false;
468 }
469
Jernej Skrabec5a088482023-04-10 10:21:11 +0200470 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xabc);
471 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100472 for (i = 0; i < 9; i++) {
473 val1 = readl(&ptr1[i]);
474 val2 = readl(&ptr2[i]);
475 if (val1 - val2 <= 6)
476 result = false;
477 }
478 }
479
480 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
481
Andre Przywara161812c2023-06-07 01:07:43 +0100482 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100483 /* maybe last parameter should be 1? */
484 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
485
486 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
487 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
488
Jernej Skrabec5a088482023-04-10 10:21:11 +0200489 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100490 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
491 result = false;
492
Andre Przywara161812c2023-06-07 01:07:43 +0100493 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200494 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100495 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
496 result = false;
497 }
498
499 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
500 }
501
502 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3);
503
504 return result;
505}
506
Andre Przywara161812c2023-06-07 01:07:43 +0100507static bool mctl_phy_write_training(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100508{
509 u32 val1, val2, *ptr1, *ptr2;
510 bool result = true;
511 int i;
512
513 writel(0, SUNXI_DRAM_PHY0_BASE + 0x134);
514 writel(0, SUNXI_DRAM_PHY0_BASE + 0x138);
515 writel(0, SUNXI_DRAM_PHY0_BASE + 0x19c);
516 writel(0, SUNXI_DRAM_PHY0_BASE + 0x1a0);
517
518 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 8);
519
520 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
521 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
522
Jernej Skrabec5a088482023-04-10 10:21:11 +0200523 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100524 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
525 result = false;
526
Andre Przywara161812c2023-06-07 01:07:43 +0100527 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200528 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100529 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
530 result = false;
531 }
532
Jernej Skrabec5a088482023-04-10 10:21:11 +0200533 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x938);
534 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100535 for (i = 0; i < 9; i++) {
536 val1 = readl(&ptr1[i]);
537 val2 = readl(&ptr2[i]);
538 if (val1 - val2 <= 6)
539 result = false;
540 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200541 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x95c);
542 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x914);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100543 for (i = 0; i < 9; i++) {
544 val1 = readl(&ptr1[i]);
545 val2 = readl(&ptr2[i]);
546 if (val1 - val2 <= 6)
547 result = false;
548 }
549
Andre Przywara161812c2023-06-07 01:07:43 +0100550 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200551 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
552 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100553 for (i = 0; i < 9; i++) {
554 val1 = readl(&ptr1[i]);
555 val2 = readl(&ptr2[i]);
556 if (val1 - val2 <= 6)
557 result = false;
558 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200559 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
560 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100561 for (i = 0; i < 9; i++) {
562 val1 = readl(&ptr1[i]);
563 val2 = readl(&ptr2[i]);
564 if (val1 - val2 <= 6)
565 result = false;
566 }
567 }
568
569 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
570
Andre Przywara161812c2023-06-07 01:07:43 +0100571 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100572 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
573
574 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
575 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
576
Jernej Skrabec5a088482023-04-10 10:21:11 +0200577 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100578 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
579 result = false;
580
Andre Przywara161812c2023-06-07 01:07:43 +0100581 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200582 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100583 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
584 result = false;
585 }
586
587 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
588 }
589
590 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc);
591
592 return result;
593}
594
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100595static void mctl_phy_bit_delay_compensation(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100596{
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200597 u32 *ptr, val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100598 int i;
599
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200600 if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
601 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
602 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
603 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300604 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
605 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4, 0x80);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100606
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200607 if (para->tpr10 & BIT(30))
608 val = para->tpr11 & 0x3f;
609 else
610 val = (para->tpr11 & 0xf) << 1;
611
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200612 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484);
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 >> 15) & 0x1e;
621 else
622 val = (para->tpr11 >> 15) & 0x1e;
623
624 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4d0);
625 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x590);
626 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4cc);
627 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x58c);
628
629 if (para->tpr10 & BIT(30))
630 val = (para->tpr11 >> 8) & 0x3f;
631 else
632 val = (para->tpr11 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100633
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200634 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
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 >> 19) & 0x1e;
643 else
644 val = (para->tpr11 >> 19) & 0x1e;
645
646 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x524);
647 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e4);
648 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x520);
649 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e0);
650
651 if (para->tpr10 & BIT(30))
652 val = (para->tpr11 >> 16) & 0x3f;
653 else
654 val = (para->tpr11 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100655
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200656 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604);
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 >> 23) & 0x1e;
665 else
666 val = (para->tpr11 >> 23) & 0x1e;
667
668 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x650);
669 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x710);
670 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x64c);
671 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x70c);
672
673 if (para->tpr10 & BIT(30))
674 val = (para->tpr11 >> 24) & 0x3f;
675 else
676 val = (para->tpr11 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100677
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200678 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658);
679 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200680 writel_relaxed(val, ptr);
681 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200682 ptr += 2;
683 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200684
685 if (para->tpr10 & BIT(30))
686 val = (para->odt_en >> 27) & 0x1e;
687 else
688 val = (para->tpr11 >> 27) & 0x1e;
689
690 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a4);
691 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x764);
692 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a0);
693 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x760);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100694
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200695 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100696
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200697 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
698 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100699
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200700 if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
701 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
702 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100703
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200704 if (para->tpr10 & BIT(30))
705 val = para->tpr12 & 0x3f;
706 else
707 val = (para->tpr12 & 0xf) << 1;
708
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200709 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480);
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 << 1) & 0x1e;
718 else
719 val = (para->tpr12 >> 15) & 0x1e;
720
721 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x528);
722 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e8);
723 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4c8);
724 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x588);
725
726 if (para->tpr10 & BIT(30))
727 val = (para->tpr12 >> 8) & 0x3f;
728 else
729 val = (para->tpr12 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100730
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200731 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
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 >> 3) & 0x1e;
740 else
741 val = (para->tpr12 >> 19) & 0x1e;
742
743 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x52c);
744 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5ec);
745 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x51c);
746 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5dc);
747
748 if (para->tpr10 & BIT(30))
749 val = (para->tpr12 >> 16) & 0x3f;
750 else
751 val = (para->tpr12 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100752
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200753 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600);
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 >> 7) & 0x1e;
762 else
763 val = (para->tpr12 >> 23) & 0x1e;
764
765 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a8);
766 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x768);
767 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x648);
768 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x708);
769
770 if (para->tpr10 & BIT(30))
771 val = (para->tpr12 >> 24) & 0x3f;
772 else
773 val = (para->tpr12 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100774
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200775 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
776 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200777 writel_relaxed(val, ptr);
778 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200779 ptr += 2;
780 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200781
782 if (para->tpr10 & BIT(30))
783 val = (para->odt_en >> 11) & 0x1e;
784 else
785 val = (para->tpr12 >> 27) & 0x1e;
786
787 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6ac);
788 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x76c);
789 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x69c);
790 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x75c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100791
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200792 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100793
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200794 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
795 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100796}
797
Andre Przywara161812c2023-06-07 01:07:43 +0100798static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para,
799 const struct dram_config *config)
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200800{
801 u32 val, *ptr;
802 int i;
803
804 if (para->tpr0 & BIT(30))
805 val = (para->tpr0 >> 7) & 0x3e;
806 else
807 val = (para->tpr10 >> 3) & 0x1e;
808
809 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
810 for (i = 0; i < 32; i++)
811 writel(val, &ptr[i]);
812
813 val = (para->tpr10 << 1) & 0x1e;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200814 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200815 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
816 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200817 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200818
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300819 val = (para->tpr10 >> 7) & 0x1e;
820 switch (para->type) {
821 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100822 if (para->tpr2 & 1) {
823 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
824 if (config->ranks == 2) {
825 val = (para->tpr10 >> 11) & 0x1e;
826 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
827 }
828 if (para->tpr0 & BIT(31)) {
829 val = (para->tpr0 << 1) & 0x3e;
830 writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
831 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
832 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
833 }
834 } else {
835 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
836 if (config->ranks == 2) {
837 val = (para->tpr10 >> 11) & 0x1e;
838 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
839 }
840 if (para->tpr0 & BIT(31)) {
841 val = (para->tpr0 << 1) & 0x3e;
842 writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
843 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
844 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
845 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200846 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300847 break;
848 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100849 if (para->tpr2 & 1) {
850 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a0);
851 if (config->ranks == 2) {
852 val = (para->tpr10 >> 11) & 0x1e;
853 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
854 }
855 } else {
856 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e8);
857 if (config->ranks == 2) {
858 val = (para->tpr10 >> 11) & 0x1e;
859 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f8);
860 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200861 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300862 break;
863 case SUNXI_DRAM_TYPE_LPDDR4:
864 if (para->tpr2 & 1) {
865 writel(val, SUNXI_DRAM_PHY0_BASE + 0x788);
866 } else {
867 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
868 };
869 break;
870 case SUNXI_DRAM_TYPE_DDR4:
871 default:
872 panic("This DRAM setup is currently not supported.\n");
873 };
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200874}
875
Andre Przywara161812c2023-06-07 01:07:43 +0100876static bool mctl_phy_init(const struct dram_para *para,
877 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100878{
879 struct sunxi_mctl_com_reg * const mctl_com =
880 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
881 struct sunxi_mctl_ctl_reg * const mctl_ctl =
882 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200883 u32 val, val2, *ptr, mr0, mr2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100884 int i;
885
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300886 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
887 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4,0x80);
888
Andre Przywara161812c2023-06-07 01:07:43 +0100889 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100890 val = 0xf;
891 else
892 val = 3;
893 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
894
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300895 switch (para->type) {
896 case SUNXI_DRAM_TYPE_DDR3:
897 if (para->tpr2 & 0x100) {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100898 val = 9;
899 val2 = 7;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300900 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100901 val = 13;
902 val2 = 9;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300903 }
904 break;
905 case SUNXI_DRAM_TYPE_LPDDR3:
906 if (para->tpr2 & 0x100) {
907 val = 12;
908 val2 = 6;
909 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100910 val = 14;
911 val2 = 8;
912 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300913 break;
914 case SUNXI_DRAM_TYPE_LPDDR4:
915 val = 20;
916 val2 = 10;
917 break;
918 case SUNXI_DRAM_TYPE_DDR4:
919 default:
920 panic("This DRAM setup is currently not supported.\n");
921 };
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200922
923 writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
924 writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
925 writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
926 writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100927
928 writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
929 writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
930 writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
931 writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
932
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200933 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
934 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
935 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
936 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100937
Jernej Skrabec5a088482023-04-10 10:21:11 +0200938 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100939 for (i = 0; i < ARRAY_SIZE(phy_init); i++)
940 writel(phy_init[i], &ptr[i]);
941
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200942 if (para->tpr10 & TPR10_CA_BIT_DELAY)
Andre Przywara161812c2023-06-07 01:07:43 +0100943 mctl_phy_ca_bit_delay_compensation(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100944
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300945 switch (para->type) {
946 case SUNXI_DRAM_TYPE_DDR3:
947 val = para->tpr6 & 0xff;
948 break;
949 case SUNXI_DRAM_TYPE_LPDDR3:
950 val = para->tpr6 >> 8 & 0xff;
951 break;
952 case SUNXI_DRAM_TYPE_LPDDR4:
953 val = para->tpr6 >> 24 & 0xff;
954 break;
955 case SUNXI_DRAM_TYPE_DDR4:
956 default:
957 panic("This DRAM setup is currently not supported.\n");
958 };
959
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100960 writel(val, SUNXI_DRAM_PHY0_BASE + 0x3dc);
961 writel(val, SUNXI_DRAM_PHY0_BASE + 0x45c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100962
Jernej Skrabec64712da2023-04-10 10:21:14 +0200963 mctl_phy_configure_odt(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100964
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300965 switch (para->type) {
966 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100967 val = 0x0a;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300968 break;
969 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100970 val = 0x0b;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300971 break;
972 case SUNXI_DRAM_TYPE_LPDDR4:
973 val = 0x0d;
974 break;
975 case SUNXI_DRAM_TYPE_DDR4:
976 default:
977 panic("This DRAM setup is currently not supported.\n");
978 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100979 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x7, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100980
981 if (para->clk <= 672)
982 writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
983 if (para->clk > 500) {
984 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
985 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
986 } else {
987 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
988 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
989 }
990
991 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
992
Jernej Skrabec5a088482023-04-10 10:21:11 +0200993 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100994
995 writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
996 clrbits_le32(&mctl_com->unk_0x500, 0x200);
997
998 writel(0, &mctl_ctl->swctl);
999 setbits_le32(&mctl_ctl->dfimisc, 1);
1000
1001 /* start DFI init */
1002 setbits_le32(&mctl_ctl->dfimisc, 0x20);
1003 writel(1, &mctl_ctl->swctl);
1004 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1005 /* poll DFI init complete */
1006 mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
1007 writel(0, &mctl_ctl->swctl);
1008 clrbits_le32(&mctl_ctl->dfimisc, 0x20);
1009
1010 clrbits_le32(&mctl_ctl->pwrctl, 0x20);
1011 writel(1, &mctl_ctl->swctl);
1012 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1013 mctl_await_completion(&mctl_ctl->statr, 3, 1);
1014
1015 writel(0, &mctl_ctl->swctl);
1016 clrbits_le32(&mctl_ctl->dfimisc, 1);
1017
1018 writel(1, &mctl_ctl->swctl);
1019 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1020
Jernej Skrabecac8154d2023-04-10 10:21:19 +02001021 if (para->tpr2 & 0x100) {
1022 mr0 = 0x1b50;
1023 mr2 = 0x10;
1024 } else {
1025 mr0 = 0x1f14;
1026 mr2 = 0x20;
1027 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001028 switch (para->type) {
1029 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001030 writel(mr0, &mctl_ctl->mrctrl1);
1031 writel(0x80000030, &mctl_ctl->mrctrl0);
1032 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001033
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001034 writel(4, &mctl_ctl->mrctrl1);
1035 writel(0x80001030, &mctl_ctl->mrctrl0);
1036 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001037
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001038 writel(mr2, &mctl_ctl->mrctrl1);
1039 writel(0x80002030, &mctl_ctl->mrctrl0);
1040 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001041
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001042 writel(0, &mctl_ctl->mrctrl1);
1043 writel(0x80003030, &mctl_ctl->mrctrl0);
1044 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001045 break;
1046 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001047 writel(mr0, &mctl_ctl->mrctrl1);
1048 writel(0x800000f0, &mctl_ctl->mrctrl0);
1049 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1050
1051 writel(4, &mctl_ctl->mrctrl1);
1052 writel(0x800000f0, &mctl_ctl->mrctrl0);
1053 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1054
1055 writel(mr2, &mctl_ctl->mrctrl1);
1056 writel(0x800000f0, &mctl_ctl->mrctrl0);
1057 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1058
1059 writel(0x301, &mctl_ctl->mrctrl1);
1060 writel(0x800000f0, &mctl_ctl->mrctrl0);
1061 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001062 break;
1063 case SUNXI_DRAM_TYPE_LPDDR4:
1064 writel(0x0, &mctl_ctl->mrctrl1);
1065 writel(0x80000030, &mctl_ctl->mrctrl0);
1066 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1067
1068 writel(0x134, &mctl_ctl->mrctrl1);
1069 writel(0x80000030, &mctl_ctl->mrctrl0);
1070 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1071
1072 writel(0x21b, &mctl_ctl->mrctrl1);
1073 writel(0x80000030, &mctl_ctl->mrctrl0);
1074 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1075
1076 writel(0x333, &mctl_ctl->mrctrl1);
1077 writel(0x80000030, &mctl_ctl->mrctrl0);
1078 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1079
1080 writel(0x403, &mctl_ctl->mrctrl1);
1081 writel(0x80000030, &mctl_ctl->mrctrl0);
1082 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1083
1084 writel(0xb04, &mctl_ctl->mrctrl1);
1085 writel(0x80000030, &mctl_ctl->mrctrl0);
1086 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1087
1088 writel(0xc72, &mctl_ctl->mrctrl1);
1089 writel(0x80000030, &mctl_ctl->mrctrl0);
1090 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1091
1092 writel(0xe09, &mctl_ctl->mrctrl1);
1093 writel(0x80000030, &mctl_ctl->mrctrl0);
1094 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1095
1096 writel(0x1624, &mctl_ctl->mrctrl1);
1097 writel(0x80000030, &mctl_ctl->mrctrl0);
1098 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1099 break;
1100 case SUNXI_DRAM_TYPE_DDR4:
1101 default:
1102 panic("This DRAM setup is currently not supported.\n");
1103 };
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001104
1105 writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
1106
1107 writel(0, &mctl_ctl->swctl);
1108 clrbits_le32(&mctl_ctl->rfshctl3, 1);
1109 writel(1, &mctl_ctl->swctl);
1110
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001111 if (para->tpr10 & TPR10_WRITE_LEVELING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001112 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001113 if (mctl_phy_write_leveling(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001114 break;
1115 if (i == 5) {
1116 debug("write leveling failed!\n");
1117 return false;
1118 }
1119 }
1120
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001121 if (para->tpr10 & TPR10_READ_CALIBRATION) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001122 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001123 if (mctl_phy_read_calibration(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001124 break;
1125 if (i == 5) {
1126 debug("read calibration failed!\n");
1127 return false;
1128 }
1129 }
1130
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001131 if (para->tpr10 & TPR10_READ_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001132 for (i = 0; i < 5; i++)
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001133 if (mctl_phy_read_training(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001134 break;
1135 if (i == 5) {
1136 debug("read training failed!\n");
1137 return false;
1138 }
1139 }
1140
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001141 if (para->tpr10 & TPR10_WRITE_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001142 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001143 if (mctl_phy_write_training(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001144 break;
1145 if (i == 5) {
1146 debug("write training failed!\n");
1147 return false;
1148 }
1149 }
1150
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001151 mctl_phy_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001152
1153 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
1154
1155 return true;
1156}
1157
Andre Przywara161812c2023-06-07 01:07:43 +01001158static bool mctl_ctrl_init(const struct dram_para *para,
1159 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001160{
1161 struct sunxi_mctl_com_reg * const mctl_com =
1162 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
1163 struct sunxi_mctl_ctl_reg * const mctl_ctl =
1164 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
1165 u32 reg_val;
1166
1167 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
1168 writel(0x8000, &mctl_ctl->clken);
1169
1170 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1171
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001172 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
1173 writel(1, SUNXI_DRAM_COM_BASE + 0x50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001174 clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
1175
1176 writel(0, &mctl_ctl->hwlpctl);
1177
1178 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1179
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001180 reg_val = MSTR_ACTIVE_RANKS(config->ranks);
1181 switch (para->type) {
1182 case SUNXI_DRAM_TYPE_DDR3:
1183 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
1184 break;
1185 case SUNXI_DRAM_TYPE_LPDDR3:
1186 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_LPDDR3;
1187 break;
1188 case SUNXI_DRAM_TYPE_LPDDR4:
1189 reg_val |= MSTR_BURST_LENGTH(16) | MSTR_DEVICETYPE_LPDDR4;
1190 break;
1191 case SUNXI_DRAM_TYPE_DDR4:
1192 default:
1193 panic("This DRAM setup is currently not supported.\n");
1194 };
Andre Przywara161812c2023-06-07 01:07:43 +01001195 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001196 reg_val |= MSTR_BUSWIDTH_FULL;
1197 else
1198 reg_val |= MSTR_BUSWIDTH_HALF;
1199 writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
1200
Andre Przywara161812c2023-06-07 01:07:43 +01001201 if (config->ranks == 2)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001202 writel(0x0303, &mctl_ctl->odtmap);
1203 else
1204 writel(0x0201, &mctl_ctl->odtmap);
1205
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001206 switch (para->type) {
1207 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001208 reg_val = 0x06000400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001209 break;
1210 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001211 reg_val = 0x09020400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001212 break;
1213 case SUNXI_DRAM_TYPE_LPDDR4:
1214 reg_val = 0x04000400;
1215 break;
1216 case SUNXI_DRAM_TYPE_DDR4:
1217 default:
1218 panic("This DRAM setup is currently not supported.\n");
1219 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001220 writel(reg_val, &mctl_ctl->odtcfg);
1221 writel(reg_val, &mctl_ctl->unk_0x2240);
1222 writel(reg_val, &mctl_ctl->unk_0x3240);
1223 writel(reg_val, &mctl_ctl->unk_0x4240);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001224
Jernej Skrabec472d4042023-04-10 10:21:10 +02001225 writel(BIT(31), &mctl_com->cr);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001226
Andre Przywara161812c2023-06-07 01:07:43 +01001227 mctl_set_addrmap(config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001228
1229 mctl_set_timing_params(para);
1230
1231 writel(0, &mctl_ctl->pwrctl);
1232
1233 setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
1234 setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
1235 setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
1236 setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
1237 setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
1238
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001239 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
1240 setbits_le32(&mctl_ctl->dbictl, 0x1);
1241
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001242 setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1243 clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
1244
1245 writel(0, &mctl_com->maer0);
1246 writel(0, &mctl_com->maer1);
1247 writel(0, &mctl_com->maer2);
1248
1249 writel(0x20, &mctl_ctl->pwrctl);
1250 setbits_le32(&mctl_ctl->clken, BIT(8));
1251
1252 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
1253 /* this write seems to enable PHY MMIO region */
1254 setbits_le32(&mctl_com->unk_0x500, BIT(24));
1255
Andre Przywara161812c2023-06-07 01:07:43 +01001256 if (!mctl_phy_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001257 return false;
1258
1259 writel(0, &mctl_ctl->swctl);
1260 clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1261
1262 setbits_le32(&mctl_com->unk_0x014, BIT(31));
1263 writel(0xffffffff, &mctl_com->maer0);
1264 writel(0x7ff, &mctl_com->maer1);
1265 writel(0xffff, &mctl_com->maer2);
1266
1267 writel(1, &mctl_ctl->swctl);
1268 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1269
1270 return true;
1271}
1272
Andre Przywara161812c2023-06-07 01:07:43 +01001273static bool mctl_core_init(const struct dram_para *para,
1274 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001275{
Andre Przywaraa21a22c2023-06-07 01:07:42 +01001276 mctl_sys_init(para->clk);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001277
Andre Przywara161812c2023-06-07 01:07:43 +01001278 return mctl_ctrl_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001279}
1280
Andre Przywara161812c2023-06-07 01:07:43 +01001281static void mctl_auto_detect_rank_width(const struct dram_para *para,
1282 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001283{
1284 /* this is minimum size that it's supported */
Andre Przywara161812c2023-06-07 01:07:43 +01001285 config->cols = 8;
1286 config->rows = 13;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001287
1288 /*
1289 * Strategy here is to test most demanding combination first and least
1290 * demanding last, otherwise HW might not be fully utilized. For
1291 * example, half bus width and rank = 1 combination would also work
1292 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
1293 * visible.
1294 */
1295
1296 debug("testing 32-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001297 config->bus_full_width = 1;
1298 config->ranks = 2;
1299 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001300 return;
1301
1302 debug("testing 32-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001303 config->bus_full_width = 1;
1304 config->ranks = 1;
1305 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001306 return;
1307
1308 debug("testing 16-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001309 config->bus_full_width = 0;
1310 config->ranks = 2;
1311 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001312 return;
1313
1314 debug("testing 16-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001315 config->bus_full_width = 0;
1316 config->ranks = 1;
1317 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001318 return;
1319
1320 panic("This DRAM setup is currently not supported.\n");
1321}
1322
Andre Przywara161812c2023-06-07 01:07:43 +01001323static void mctl_auto_detect_dram_size(const struct dram_para *para,
1324 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001325{
1326 /* detect row address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001327 config->cols = 8;
1328 config->rows = 18;
1329 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001330
Andre Przywara161812c2023-06-07 01:07:43 +01001331 for (config->rows = 13; config->rows < 18; config->rows++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001332 /* 8 banks, 8 bit per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001333 if (mctl_mem_matches((1 << (config->rows + config->cols +
1334 4 + config->bus_full_width))))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001335 break;
1336 }
1337
1338 /* detect column address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001339 config->cols = 11;
1340 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001341
Andre Przywara161812c2023-06-07 01:07:43 +01001342 for (config->cols = 8; config->cols < 11; config->cols++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001343 /* 8 bits per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001344 if (mctl_mem_matches(1 << (config->cols + 1 +
1345 config->bus_full_width)))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001346 break;
1347 }
1348}
1349
Andre Przywara161812c2023-06-07 01:07:43 +01001350static unsigned long mctl_calc_size(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001351{
Andre Przywara161812c2023-06-07 01:07:43 +01001352 u8 width = config->bus_full_width ? 4 : 2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001353
1354 /* 8 banks */
Andre Przywara161812c2023-06-07 01:07:43 +01001355 return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001356}
1357
Andre Przywara161812c2023-06-07 01:07:43 +01001358static const struct dram_para para = {
1359 .clk = CONFIG_DRAM_CLK,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001360#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Andre Przywara161812c2023-06-07 01:07:43 +01001361 .type = SUNXI_DRAM_TYPE_DDR3,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001362#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
1363 .type = SUNXI_DRAM_TYPE_LPDDR3,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001364#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
1365 .type = SUNXI_DRAM_TYPE_LPDDR4,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001366#endif
Andre Przywara161812c2023-06-07 01:07:43 +01001367 .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
1368 .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
1369 .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
1370 .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
1371 .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
1372 .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001373 .tpr6 = CONFIG_DRAM_SUN50I_H616_TPR6,
Andre Przywara161812c2023-06-07 01:07:43 +01001374 .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
1375 .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
1376 .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
1377};
1378
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001379unsigned long sunxi_dram_init(void)
1380{
Jernej Skrabece04cd492022-01-30 15:27:13 +01001381 struct sunxi_prcm_reg *const prcm =
1382 (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +01001383 struct dram_config config;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001384 unsigned long size;
1385
Jernej Skrabece04cd492022-01-30 15:27:13 +01001386 setbits_le32(&prcm->res_cal_ctrl, BIT(8));
1387 clrbits_le32(&prcm->ohms240, 0x3f);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001388
Andre Przywara161812c2023-06-07 01:07:43 +01001389 mctl_auto_detect_rank_width(&para, &config);
1390 mctl_auto_detect_dram_size(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001391
Andre Przywara161812c2023-06-07 01:07:43 +01001392 mctl_core_init(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001393
Andre Przywara161812c2023-06-07 01:07:43 +01001394 size = mctl_calc_size(&config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001395
1396 mctl_set_master_priority();
1397
1398 return size;
1399};