blob: 37c139e0eea5eb4f20a2d4eb0b42705c1724931c [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 */
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010015#include <init.h>
16#include <log.h>
17#include <asm/io.h>
18#include <asm/arch/clock.h>
19#include <asm/arch/dram.h>
20#include <asm/arch/cpu.h>
Jernej Skrabece04cd492022-01-30 15:27:13 +010021#include <asm/arch/prcm.h>
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010022#include <linux/bitops.h>
23#include <linux/delay.h>
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010024
25enum {
26 MBUS_QOS_LOWEST = 0,
27 MBUS_QOS_LOW,
28 MBUS_QOS_HIGH,
29 MBUS_QOS_HIGHEST
30};
31
Andre Przywara16f6f792023-06-07 01:07:41 +010032static void mbus_configure_port(u8 port,
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010033 bool bwlimit,
34 bool priority,
35 u8 qos,
36 u8 waittime,
37 u8 acs,
38 u16 bwl0,
39 u16 bwl1,
40 u16 bwl2)
41{
42 struct sunxi_mctl_com_reg * const mctl_com =
43 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
44
45 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
46 | (priority ? (1 << 1) : 0)
47 | ((qos & 0x3) << 2)
48 | ((waittime & 0xf) << 4)
49 | ((acs & 0xff) << 8)
50 | (bwl0 << 16) );
51 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
52
53 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
54 writel_relaxed(cfg0, &mctl_com->master[port].cfg0);
55 writel_relaxed(cfg1, &mctl_com->master[port].cfg1);
56}
57
58#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
59 mbus_configure_port(port, bwlimit, false, \
60 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
61
62static void mctl_set_master_priority(void)
63{
64 struct sunxi_mctl_com_reg * const mctl_com =
65 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
66
67 /* enable bandwidth limit windows and set windows size 1us */
68 writel(399, &mctl_com->tmr);
69 writel(BIT(16), &mctl_com->bwcr);
70
71 MBUS_CONF( 0, true, HIGHEST, 0, 256, 128, 100);
72 MBUS_CONF( 1, true, HIGH, 0, 1536, 1400, 256);
73 MBUS_CONF( 2, true, HIGHEST, 0, 512, 256, 96);
74 MBUS_CONF( 3, true, HIGH, 0, 256, 100, 80);
75 MBUS_CONF( 4, true, HIGH, 2, 8192, 5500, 5000);
76 MBUS_CONF( 5, true, HIGH, 2, 100, 64, 32);
77 MBUS_CONF( 6, true, HIGH, 2, 100, 64, 32);
78 MBUS_CONF( 8, true, HIGH, 0, 256, 128, 64);
79 MBUS_CONF(11, true, HIGH, 0, 256, 128, 100);
80 MBUS_CONF(14, true, HIGH, 0, 1024, 256, 64);
81 MBUS_CONF(16, true, HIGHEST, 6, 8192, 2800, 2400);
82 MBUS_CONF(21, true, HIGHEST, 6, 2048, 768, 512);
83 MBUS_CONF(25, true, HIGHEST, 0, 100, 64, 32);
84 MBUS_CONF(26, true, HIGH, 2, 8192, 5500, 5000);
85 MBUS_CONF(37, true, HIGH, 0, 256, 128, 64);
86 MBUS_CONF(38, true, HIGH, 2, 100, 64, 32);
87 MBUS_CONF(39, true, HIGH, 2, 8192, 5500, 5000);
88 MBUS_CONF(40, true, HIGH, 2, 100, 64, 32);
89
90 dmb();
91}
92
Andre Przywaraa21a22c2023-06-07 01:07:42 +010093static void mctl_sys_init(u32 clk_rate)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010094{
95 struct sunxi_ccm_reg * const ccm =
96 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
97 struct sunxi_mctl_com_reg * const mctl_com =
98 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
99 struct sunxi_mctl_ctl_reg * const mctl_ctl =
100 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
101
102 /* Put all DRAM-related blocks to reset state */
103 clrbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
104 clrbits_le32(&ccm->mbus_cfg, MBUS_RESET);
105 clrbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
106 udelay(5);
107 clrbits_le32(&ccm->dram_gate_reset, BIT(RESET_SHIFT));
108 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
109 clrbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
110
111 udelay(5);
112
113 /* Set PLL5 rate to doubled DRAM clock rate */
114 writel(CCM_PLL5_CTRL_EN | CCM_PLL5_LOCK_EN | CCM_PLL5_OUT_EN |
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100115 CCM_PLL5_CTRL_N(clk_rate * 2 / 24), &ccm->pll5_cfg);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100116 mctl_await_completion(&ccm->pll5_cfg, CCM_PLL5_LOCK, CCM_PLL5_LOCK);
117
118 /* Configure DRAM mod clock */
119 writel(DRAM_CLK_SRC_PLL5, &ccm->dram_clk_cfg);
120 writel(BIT(RESET_SHIFT), &ccm->dram_gate_reset);
121 udelay(5);
122 setbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
123
124 /* Disable all channels */
125 writel(0, &mctl_com->maer0);
126 writel(0, &mctl_com->maer1);
127 writel(0, &mctl_com->maer2);
128
129 /* Configure MBUS and enable DRAM mod reset */
130 setbits_le32(&ccm->mbus_cfg, MBUS_RESET);
131 setbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
132
133 clrbits_le32(&mctl_com->unk_0x500, BIT(25));
134
135 setbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
136 udelay(5);
137
138 /* Unknown hack, which enables access of mctl_ctl regs */
139 writel(0x8000, &mctl_ctl->clken);
140}
141
Andre Przywara161812c2023-06-07 01:07:43 +0100142static void mctl_set_addrmap(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100143{
144 struct sunxi_mctl_ctl_reg * const mctl_ctl =
145 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +0100146 u8 cols = config->cols;
147 u8 rows = config->rows;
148 u8 ranks = config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100149
Andre Przywara161812c2023-06-07 01:07:43 +0100150 if (!config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100151 cols -= 1;
152
153 /* Ranks */
154 if (ranks == 2)
155 mctl_ctl->addrmap[0] = rows + cols - 3;
156 else
157 mctl_ctl->addrmap[0] = 0x1F;
158
159 /* Banks, hardcoded to 8 banks now */
160 mctl_ctl->addrmap[1] = (cols - 2) | (cols - 2) << 8 | (cols - 2) << 16;
161
162 /* Columns */
163 mctl_ctl->addrmap[2] = 0;
164 switch (cols) {
165 case 7:
166 mctl_ctl->addrmap[3] = 0x1F1F1F00;
167 mctl_ctl->addrmap[4] = 0x1F1F;
168 break;
169 case 8:
170 mctl_ctl->addrmap[3] = 0x1F1F0000;
171 mctl_ctl->addrmap[4] = 0x1F1F;
172 break;
173 case 9:
174 mctl_ctl->addrmap[3] = 0x1F000000;
175 mctl_ctl->addrmap[4] = 0x1F1F;
176 break;
177 case 10:
178 mctl_ctl->addrmap[3] = 0;
179 mctl_ctl->addrmap[4] = 0x1F1F;
180 break;
181 case 11:
182 mctl_ctl->addrmap[3] = 0;
183 mctl_ctl->addrmap[4] = 0x1F00;
184 break;
185 case 12:
186 mctl_ctl->addrmap[3] = 0;
187 mctl_ctl->addrmap[4] = 0;
188 break;
189 default:
190 panic("Unsupported DRAM configuration: column number invalid\n");
191 }
192
193 /* Rows */
194 mctl_ctl->addrmap[5] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
195 switch (rows) {
196 case 13:
197 mctl_ctl->addrmap[6] = (cols - 3) | 0x0F0F0F00;
198 mctl_ctl->addrmap[7] = 0x0F0F;
199 break;
200 case 14:
201 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | 0x0F0F0000;
202 mctl_ctl->addrmap[7] = 0x0F0F;
203 break;
204 case 15:
205 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | 0x0F000000;
206 mctl_ctl->addrmap[7] = 0x0F0F;
207 break;
208 case 16:
209 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
210 mctl_ctl->addrmap[7] = 0x0F0F;
211 break;
212 case 17:
213 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
214 mctl_ctl->addrmap[7] = (cols - 3) | 0x0F00;
215 break;
216 case 18:
217 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
218 mctl_ctl->addrmap[7] = (cols - 3) | ((cols - 3) << 8);
219 break;
220 default:
221 panic("Unsupported DRAM configuration: row number invalid\n");
222 }
223
224 /* Bank groups, DDR4 only */
225 mctl_ctl->addrmap[8] = 0x3F3F;
226}
227
228static const u8 phy_init[] = {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100229#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100230 0x07, 0x0b, 0x02, 0x16, 0x0d, 0x0e, 0x14, 0x19,
231 0x0a, 0x15, 0x03, 0x13, 0x04, 0x0c, 0x10, 0x06,
232 0x0f, 0x11, 0x1a, 0x01, 0x12, 0x17, 0x00, 0x08,
233 0x09, 0x05, 0x18
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100234#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
235 0x18, 0x06, 0x00, 0x05, 0x04, 0x03, 0x09, 0x02,
236 0x08, 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
237 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07,
238 0x17, 0x19, 0x1a
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300239#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
240 0x02, 0x00, 0x17, 0x05, 0x04, 0x19, 0x06, 0x07,
241 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
242 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x01,
243 0x18, 0x03, 0x1a
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100244#endif
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100245};
246
Andre Przywara1af6f152023-09-07 20:38:46 +0100247#define MASK_BYTE(reg, nr) (((reg) >> ((nr) * 8)) & 0x1f)
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100248static void mctl_phy_configure_odt(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100249{
Andre Przywara1af6f152023-09-07 20:38:46 +0100250 uint32_t val_lo, val_hi;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100251
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300252 /*
253 * This part should be applicable to all memory types, but is
254 * usually found in LPDDR4 bootloaders. Therefore, we will leave
255 * only for this type of memory.
256 */
257 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
258 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x390, BIT(5), BIT(4));
259 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3d0, BIT(5), BIT(4));
260 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x410, BIT(5), BIT(4));
261 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x450, BIT(5), BIT(4));
262 }
263
Andre Przywara1af6f152023-09-07 20:38:46 +0100264 val_lo = para->dx_dri;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300265 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0x04040404 : para->dx_dri;
Andre Przywara1af6f152023-09-07 20:38:46 +0100266 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x388);
267 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x38c);
268 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c8);
269 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3cc);
270 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x408);
271 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x40c);
272 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x448);
273 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x44c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100274
Andre Przywara1af6f152023-09-07 20:38:46 +0100275 val_lo = para->ca_dri;
276 val_hi = para->ca_dri;
277 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x340);
278 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x344);
279 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x348);
280 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x34c);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200281
Andre Przywara1af6f152023-09-07 20:38:46 +0100282 val_lo = (para->type == SUNXI_DRAM_TYPE_LPDDR3) ? 0 : para->dx_odt;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300283 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0 : para->dx_odt;
Andre Przywara1af6f152023-09-07 20:38:46 +0100284 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x380);
285 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x384);
286 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c0);
287 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3c4);
288 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x400);
289 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x404);
290 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x440);
291 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x444);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100292
293 dmb();
294}
295
Andre Przywara161812c2023-06-07 01:07:43 +0100296static bool mctl_phy_write_leveling(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100297{
298 bool result = true;
299 u32 val;
300
301 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x80);
302 writel(4, SUNXI_DRAM_PHY0_BASE + 0xc);
303 writel(0x40, SUNXI_DRAM_PHY0_BASE + 0x10);
304
305 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
306
Andre Przywara161812c2023-06-07 01:07:43 +0100307 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100308 val = 0xf;
309 else
310 val = 3;
311
Jernej Skrabec5a088482023-04-10 10:21:11 +0200312 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100313
314 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
315
316 val = readl(SUNXI_DRAM_PHY0_BASE + 0x258);
317 if (val == 0 || val == 0x3f)
318 result = false;
319 val = readl(SUNXI_DRAM_PHY0_BASE + 0x25c);
320 if (val == 0 || val == 0x3f)
321 result = false;
322 val = readl(SUNXI_DRAM_PHY0_BASE + 0x318);
323 if (val == 0 || val == 0x3f)
324 result = false;
325 val = readl(SUNXI_DRAM_PHY0_BASE + 0x31c);
326 if (val == 0 || val == 0x3f)
327 result = false;
328
329 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
330
Andre Przywara161812c2023-06-07 01:07:43 +0100331 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100332 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
333
334 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
335
Andre Przywara161812c2023-06-07 01:07:43 +0100336 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100337 val = 0xf;
338 else
339 val = 3;
340
Jernej Skrabec5a088482023-04-10 10:21:11 +0200341 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100342
343 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
344 }
345
346 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
347
348 return result;
349}
350
Andre Przywara161812c2023-06-07 01:07:43 +0100351static bool mctl_phy_read_calibration(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100352{
353 bool result = true;
354 u32 val, tmp;
355
356 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
357
358 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
359
Andre Przywara161812c2023-06-07 01:07:43 +0100360 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100361 val = 0xf;
362 else
363 val = 3;
364
365 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
366 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
367 result = false;
368 break;
369 }
370 }
371
372 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
373
374 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
375
Andre Przywara161812c2023-06-07 01:07:43 +0100376 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100377 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
378
379 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
380
381 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
382 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
383 result = false;
384 break;
385 }
386 }
387
Jernej Skrabec4e048422022-01-29 16:58:43 +0100388 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100389 }
390
391 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
392
393 val = readl(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
394 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
395 if (val < tmp)
396 val = tmp;
397 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
398 if (val < tmp)
399 val = tmp;
400 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
401 if (val < tmp)
402 val = tmp;
403 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
404
405 setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
406
407 return result;
408}
409
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300410static bool mctl_phy_read_training(const struct dram_para *para,
411 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100412{
413 u32 val1, val2, *ptr1, *ptr2;
414 bool result = true;
415 int i;
416
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300417 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
418 writel(0, SUNXI_DRAM_PHY0_BASE + 0x800);
419 writel(0, SUNXI_DRAM_PHY0_BASE + 0x81c);
420 }
421
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100422 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
423 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x804, 0x3f, 0xf);
424 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x808, 0x3f, 0xf);
425 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa04, 0x3f, 0xf);
426 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa08, 0x3f, 0xf);
427
428 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
429 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
430
Jernej Skrabec5a088482023-04-10 10:21:11 +0200431 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100432 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
433 result = false;
434
Andre Przywara161812c2023-06-07 01:07:43 +0100435 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200436 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100437 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
438 result = false;
439 }
440
Jernej Skrabec5a088482023-04-10 10:21:11 +0200441 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x898);
442 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x850);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100443 for (i = 0; i < 9; i++) {
444 val1 = readl(&ptr1[i]);
445 val2 = readl(&ptr2[i]);
446 if (val1 - val2 <= 6)
447 result = false;
448 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200449 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
450 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x874);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100451 for (i = 0; i < 9; i++) {
452 val1 = readl(&ptr1[i]);
453 val2 = readl(&ptr2[i]);
454 if (val1 - val2 <= 6)
455 result = false;
456 }
457
Andre Przywara161812c2023-06-07 01:07:43 +0100458 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200459 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
460 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100461 for (i = 0; i < 9; i++) {
462 val1 = readl(&ptr1[i]);
463 val2 = readl(&ptr2[i]);
464 if (val1 - val2 <= 6)
465 result = false;
466 }
467
Jernej Skrabec5a088482023-04-10 10:21:11 +0200468 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xabc);
469 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100470 for (i = 0; i < 9; i++) {
471 val1 = readl(&ptr1[i]);
472 val2 = readl(&ptr2[i]);
473 if (val1 - val2 <= 6)
474 result = false;
475 }
476 }
477
478 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
479
Andre Przywara161812c2023-06-07 01:07:43 +0100480 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100481 /* maybe last parameter should be 1? */
482 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
483
484 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
485 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
486
Jernej Skrabec5a088482023-04-10 10:21:11 +0200487 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100488 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
489 result = false;
490
Andre Przywara161812c2023-06-07 01:07:43 +0100491 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200492 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100493 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
494 result = false;
495 }
496
497 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
498 }
499
500 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3);
501
502 return result;
503}
504
Andre Przywara161812c2023-06-07 01:07:43 +0100505static bool mctl_phy_write_training(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100506{
507 u32 val1, val2, *ptr1, *ptr2;
508 bool result = true;
509 int i;
510
511 writel(0, SUNXI_DRAM_PHY0_BASE + 0x134);
512 writel(0, SUNXI_DRAM_PHY0_BASE + 0x138);
513 writel(0, SUNXI_DRAM_PHY0_BASE + 0x19c);
514 writel(0, SUNXI_DRAM_PHY0_BASE + 0x1a0);
515
516 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 8);
517
518 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
519 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
520
Jernej Skrabec5a088482023-04-10 10:21:11 +0200521 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100522 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
523 result = false;
524
Andre Przywara161812c2023-06-07 01:07:43 +0100525 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200526 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100527 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
528 result = false;
529 }
530
Jernej Skrabec5a088482023-04-10 10:21:11 +0200531 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x938);
532 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100533 for (i = 0; i < 9; i++) {
534 val1 = readl(&ptr1[i]);
535 val2 = readl(&ptr2[i]);
536 if (val1 - val2 <= 6)
537 result = false;
538 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200539 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x95c);
540 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x914);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100541 for (i = 0; i < 9; i++) {
542 val1 = readl(&ptr1[i]);
543 val2 = readl(&ptr2[i]);
544 if (val1 - val2 <= 6)
545 result = false;
546 }
547
Andre Przywara161812c2023-06-07 01:07:43 +0100548 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200549 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
550 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100551 for (i = 0; i < 9; i++) {
552 val1 = readl(&ptr1[i]);
553 val2 = readl(&ptr2[i]);
554 if (val1 - val2 <= 6)
555 result = false;
556 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200557 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
558 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100559 for (i = 0; i < 9; i++) {
560 val1 = readl(&ptr1[i]);
561 val2 = readl(&ptr2[i]);
562 if (val1 - val2 <= 6)
563 result = false;
564 }
565 }
566
567 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
568
Andre Przywara161812c2023-06-07 01:07:43 +0100569 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100570 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
571
572 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
573 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
574
Jernej Skrabec5a088482023-04-10 10:21:11 +0200575 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100576 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
577 result = false;
578
Andre Przywara161812c2023-06-07 01:07:43 +0100579 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200580 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100581 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
582 result = false;
583 }
584
585 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
586 }
587
588 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc);
589
590 return result;
591}
592
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100593static void mctl_phy_bit_delay_compensation(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100594{
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200595 u32 *ptr, val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100596 int i;
597
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200598 if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
599 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
600 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
601 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300602 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
603 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4, 0x80);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100604
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200605 if (para->tpr10 & BIT(30))
606 val = para->tpr11 & 0x3f;
607 else
608 val = (para->tpr11 & 0xf) << 1;
609
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200610 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484);
611 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200612 writel_relaxed(val, ptr);
613 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200614 ptr += 2;
615 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200616
617 if (para->tpr10 & BIT(30))
618 val = (para->odt_en >> 15) & 0x1e;
619 else
620 val = (para->tpr11 >> 15) & 0x1e;
621
622 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4d0);
623 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x590);
624 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4cc);
625 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x58c);
626
627 if (para->tpr10 & BIT(30))
628 val = (para->tpr11 >> 8) & 0x3f;
629 else
630 val = (para->tpr11 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100631
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200632 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
633 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200634 writel_relaxed(val, ptr);
635 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200636 ptr += 2;
637 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200638
639 if (para->tpr10 & BIT(30))
640 val = (para->odt_en >> 19) & 0x1e;
641 else
642 val = (para->tpr11 >> 19) & 0x1e;
643
644 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x524);
645 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e4);
646 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x520);
647 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e0);
648
649 if (para->tpr10 & BIT(30))
650 val = (para->tpr11 >> 16) & 0x3f;
651 else
652 val = (para->tpr11 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100653
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200654 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604);
655 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200656 writel_relaxed(val, ptr);
657 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200658 ptr += 2;
659 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200660
661 if (para->tpr10 & BIT(30))
662 val = (para->odt_en >> 23) & 0x1e;
663 else
664 val = (para->tpr11 >> 23) & 0x1e;
665
666 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x650);
667 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x710);
668 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x64c);
669 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x70c);
670
671 if (para->tpr10 & BIT(30))
672 val = (para->tpr11 >> 24) & 0x3f;
673 else
674 val = (para->tpr11 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100675
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200676 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658);
677 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200678 writel_relaxed(val, ptr);
679 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200680 ptr += 2;
681 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200682
683 if (para->tpr10 & BIT(30))
684 val = (para->odt_en >> 27) & 0x1e;
685 else
686 val = (para->tpr11 >> 27) & 0x1e;
687
688 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a4);
689 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x764);
690 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a0);
691 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x760);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100692
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200693 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100694
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200695 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
696 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100697
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200698 if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
699 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
700 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100701
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200702 if (para->tpr10 & BIT(30))
703 val = para->tpr12 & 0x3f;
704 else
705 val = (para->tpr12 & 0xf) << 1;
706
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200707 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480);
708 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200709 writel_relaxed(val, ptr);
710 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200711 ptr += 2;
712 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200713
714 if (para->tpr10 & BIT(30))
715 val = (para->odt_en << 1) & 0x1e;
716 else
717 val = (para->tpr12 >> 15) & 0x1e;
718
719 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x528);
720 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e8);
721 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4c8);
722 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x588);
723
724 if (para->tpr10 & BIT(30))
725 val = (para->tpr12 >> 8) & 0x3f;
726 else
727 val = (para->tpr12 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100728
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200729 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
730 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200731 writel_relaxed(val, ptr);
732 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200733 ptr += 2;
734 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200735
736 if (para->tpr10 & BIT(30))
737 val = (para->odt_en >> 3) & 0x1e;
738 else
739 val = (para->tpr12 >> 19) & 0x1e;
740
741 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x52c);
742 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5ec);
743 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x51c);
744 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5dc);
745
746 if (para->tpr10 & BIT(30))
747 val = (para->tpr12 >> 16) & 0x3f;
748 else
749 val = (para->tpr12 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100750
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200751 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600);
752 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200753 writel_relaxed(val, ptr);
754 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200755 ptr += 2;
756 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200757
758 if (para->tpr10 & BIT(30))
759 val = (para->odt_en >> 7) & 0x1e;
760 else
761 val = (para->tpr12 >> 23) & 0x1e;
762
763 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a8);
764 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x768);
765 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x648);
766 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x708);
767
768 if (para->tpr10 & BIT(30))
769 val = (para->tpr12 >> 24) & 0x3f;
770 else
771 val = (para->tpr12 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100772
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200773 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
774 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200775 writel_relaxed(val, ptr);
776 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200777 ptr += 2;
778 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200779
780 if (para->tpr10 & BIT(30))
781 val = (para->odt_en >> 11) & 0x1e;
782 else
783 val = (para->tpr12 >> 27) & 0x1e;
784
785 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6ac);
786 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x76c);
787 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x69c);
788 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x75c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100789
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200790 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100791
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200792 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
793 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100794}
795
Andre Przywara161812c2023-06-07 01:07:43 +0100796static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para,
797 const struct dram_config *config)
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200798{
799 u32 val, *ptr;
800 int i;
801
802 if (para->tpr0 & BIT(30))
803 val = (para->tpr0 >> 7) & 0x3e;
804 else
805 val = (para->tpr10 >> 3) & 0x1e;
806
807 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
808 for (i = 0; i < 32; i++)
809 writel(val, &ptr[i]);
810
811 val = (para->tpr10 << 1) & 0x1e;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200812 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200813 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
814 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200815 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200816
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300817 val = (para->tpr10 >> 7) & 0x1e;
818 switch (para->type) {
819 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100820 if (para->tpr2 & 1) {
821 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
822 if (config->ranks == 2) {
823 val = (para->tpr10 >> 11) & 0x1e;
824 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
825 }
826 if (para->tpr0 & BIT(31)) {
827 val = (para->tpr0 << 1) & 0x3e;
828 writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
829 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
830 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
831 }
832 } else {
833 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
834 if (config->ranks == 2) {
835 val = (para->tpr10 >> 11) & 0x1e;
836 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
837 }
838 if (para->tpr0 & BIT(31)) {
839 val = (para->tpr0 << 1) & 0x3e;
840 writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
841 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
842 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
843 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200844 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300845 break;
846 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100847 if (para->tpr2 & 1) {
848 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a0);
849 if (config->ranks == 2) {
850 val = (para->tpr10 >> 11) & 0x1e;
851 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
852 }
853 } else {
854 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e8);
855 if (config->ranks == 2) {
856 val = (para->tpr10 >> 11) & 0x1e;
857 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f8);
858 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200859 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300860 break;
861 case SUNXI_DRAM_TYPE_LPDDR4:
862 if (para->tpr2 & 1) {
863 writel(val, SUNXI_DRAM_PHY0_BASE + 0x788);
864 } else {
865 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
866 };
867 break;
868 case SUNXI_DRAM_TYPE_DDR4:
869 default:
870 panic("This DRAM setup is currently not supported.\n");
871 };
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200872}
873
Andre Przywara161812c2023-06-07 01:07:43 +0100874static bool mctl_phy_init(const struct dram_para *para,
875 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100876{
877 struct sunxi_mctl_com_reg * const mctl_com =
878 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
879 struct sunxi_mctl_ctl_reg * const mctl_ctl =
880 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200881 u32 val, val2, *ptr, mr0, mr2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100882 int i;
883
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300884 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
885 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4,0x80);
886
Andre Przywara161812c2023-06-07 01:07:43 +0100887 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100888 val = 0xf;
889 else
890 val = 3;
891 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
892
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300893 switch (para->type) {
894 case SUNXI_DRAM_TYPE_DDR3:
895 if (para->tpr2 & 0x100) {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100896 val = 9;
897 val2 = 7;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300898 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100899 val = 13;
900 val2 = 9;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300901 }
902 break;
903 case SUNXI_DRAM_TYPE_LPDDR3:
904 if (para->tpr2 & 0x100) {
905 val = 12;
906 val2 = 6;
907 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100908 val = 14;
909 val2 = 8;
910 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300911 break;
912 case SUNXI_DRAM_TYPE_LPDDR4:
913 val = 20;
914 val2 = 10;
915 break;
916 case SUNXI_DRAM_TYPE_DDR4:
917 default:
918 panic("This DRAM setup is currently not supported.\n");
919 };
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200920
921 writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
922 writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
923 writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
924 writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100925
926 writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
927 writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
928 writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
929 writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
930
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200931 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
932 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
933 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
934 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100935
Jernej Skrabec5a088482023-04-10 10:21:11 +0200936 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100937 for (i = 0; i < ARRAY_SIZE(phy_init); i++)
938 writel(phy_init[i], &ptr[i]);
939
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200940 if (para->tpr10 & TPR10_CA_BIT_DELAY)
Andre Przywara161812c2023-06-07 01:07:43 +0100941 mctl_phy_ca_bit_delay_compensation(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100942
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300943 switch (para->type) {
944 case SUNXI_DRAM_TYPE_DDR3:
945 val = para->tpr6 & 0xff;
946 break;
947 case SUNXI_DRAM_TYPE_LPDDR3:
948 val = para->tpr6 >> 8 & 0xff;
949 break;
950 case SUNXI_DRAM_TYPE_LPDDR4:
951 val = para->tpr6 >> 24 & 0xff;
952 break;
953 case SUNXI_DRAM_TYPE_DDR4:
954 default:
955 panic("This DRAM setup is currently not supported.\n");
956 };
957
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100958 writel(val, SUNXI_DRAM_PHY0_BASE + 0x3dc);
959 writel(val, SUNXI_DRAM_PHY0_BASE + 0x45c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100960
Jernej Skrabec64712da2023-04-10 10:21:14 +0200961 mctl_phy_configure_odt(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100962
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300963 switch (para->type) {
964 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100965 val = 0x0a;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300966 break;
967 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100968 val = 0x0b;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300969 break;
970 case SUNXI_DRAM_TYPE_LPDDR4:
971 val = 0x0d;
972 break;
973 case SUNXI_DRAM_TYPE_DDR4:
974 default:
975 panic("This DRAM setup is currently not supported.\n");
976 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100977 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x7, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100978
979 if (para->clk <= 672)
980 writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
981 if (para->clk > 500) {
982 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
983 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
984 } else {
985 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
986 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
987 }
988
989 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
990
Jernej Skrabec5a088482023-04-10 10:21:11 +0200991 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100992
993 writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
994 clrbits_le32(&mctl_com->unk_0x500, 0x200);
995
996 writel(0, &mctl_ctl->swctl);
997 setbits_le32(&mctl_ctl->dfimisc, 1);
998
999 /* start DFI init */
1000 setbits_le32(&mctl_ctl->dfimisc, 0x20);
1001 writel(1, &mctl_ctl->swctl);
1002 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1003 /* poll DFI init complete */
1004 mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
1005 writel(0, &mctl_ctl->swctl);
1006 clrbits_le32(&mctl_ctl->dfimisc, 0x20);
1007
1008 clrbits_le32(&mctl_ctl->pwrctl, 0x20);
1009 writel(1, &mctl_ctl->swctl);
1010 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1011 mctl_await_completion(&mctl_ctl->statr, 3, 1);
1012
1013 writel(0, &mctl_ctl->swctl);
1014 clrbits_le32(&mctl_ctl->dfimisc, 1);
1015
1016 writel(1, &mctl_ctl->swctl);
1017 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1018
Jernej Skrabecac8154d2023-04-10 10:21:19 +02001019 if (para->tpr2 & 0x100) {
1020 mr0 = 0x1b50;
1021 mr2 = 0x10;
1022 } else {
1023 mr0 = 0x1f14;
1024 mr2 = 0x20;
1025 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001026 switch (para->type) {
1027 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001028 writel(mr0, &mctl_ctl->mrctrl1);
1029 writel(0x80000030, &mctl_ctl->mrctrl0);
1030 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001031
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001032 writel(4, &mctl_ctl->mrctrl1);
1033 writel(0x80001030, &mctl_ctl->mrctrl0);
1034 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001035
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001036 writel(mr2, &mctl_ctl->mrctrl1);
1037 writel(0x80002030, &mctl_ctl->mrctrl0);
1038 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001039
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001040 writel(0, &mctl_ctl->mrctrl1);
1041 writel(0x80003030, &mctl_ctl->mrctrl0);
1042 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001043 break;
1044 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001045 writel(mr0, &mctl_ctl->mrctrl1);
1046 writel(0x800000f0, &mctl_ctl->mrctrl0);
1047 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1048
1049 writel(4, &mctl_ctl->mrctrl1);
1050 writel(0x800000f0, &mctl_ctl->mrctrl0);
1051 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1052
1053 writel(mr2, &mctl_ctl->mrctrl1);
1054 writel(0x800000f0, &mctl_ctl->mrctrl0);
1055 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1056
1057 writel(0x301, &mctl_ctl->mrctrl1);
1058 writel(0x800000f0, &mctl_ctl->mrctrl0);
1059 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001060 break;
1061 case SUNXI_DRAM_TYPE_LPDDR4:
1062 writel(0x0, &mctl_ctl->mrctrl1);
1063 writel(0x80000030, &mctl_ctl->mrctrl0);
1064 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1065
1066 writel(0x134, &mctl_ctl->mrctrl1);
1067 writel(0x80000030, &mctl_ctl->mrctrl0);
1068 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1069
1070 writel(0x21b, &mctl_ctl->mrctrl1);
1071 writel(0x80000030, &mctl_ctl->mrctrl0);
1072 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1073
1074 writel(0x333, &mctl_ctl->mrctrl1);
1075 writel(0x80000030, &mctl_ctl->mrctrl0);
1076 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1077
1078 writel(0x403, &mctl_ctl->mrctrl1);
1079 writel(0x80000030, &mctl_ctl->mrctrl0);
1080 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1081
1082 writel(0xb04, &mctl_ctl->mrctrl1);
1083 writel(0x80000030, &mctl_ctl->mrctrl0);
1084 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1085
1086 writel(0xc72, &mctl_ctl->mrctrl1);
1087 writel(0x80000030, &mctl_ctl->mrctrl0);
1088 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1089
1090 writel(0xe09, &mctl_ctl->mrctrl1);
1091 writel(0x80000030, &mctl_ctl->mrctrl0);
1092 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1093
1094 writel(0x1624, &mctl_ctl->mrctrl1);
1095 writel(0x80000030, &mctl_ctl->mrctrl0);
1096 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1097 break;
1098 case SUNXI_DRAM_TYPE_DDR4:
1099 default:
1100 panic("This DRAM setup is currently not supported.\n");
1101 };
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001102
1103 writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
1104
1105 writel(0, &mctl_ctl->swctl);
1106 clrbits_le32(&mctl_ctl->rfshctl3, 1);
1107 writel(1, &mctl_ctl->swctl);
1108
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001109 if (para->tpr10 & TPR10_WRITE_LEVELING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001110 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001111 if (mctl_phy_write_leveling(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001112 break;
1113 if (i == 5) {
1114 debug("write leveling failed!\n");
1115 return false;
1116 }
1117 }
1118
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001119 if (para->tpr10 & TPR10_READ_CALIBRATION) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001120 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001121 if (mctl_phy_read_calibration(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001122 break;
1123 if (i == 5) {
1124 debug("read calibration failed!\n");
1125 return false;
1126 }
1127 }
1128
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001129 if (para->tpr10 & TPR10_READ_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001130 for (i = 0; i < 5; i++)
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001131 if (mctl_phy_read_training(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001132 break;
1133 if (i == 5) {
1134 debug("read training failed!\n");
1135 return false;
1136 }
1137 }
1138
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001139 if (para->tpr10 & TPR10_WRITE_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001140 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001141 if (mctl_phy_write_training(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001142 break;
1143 if (i == 5) {
1144 debug("write training failed!\n");
1145 return false;
1146 }
1147 }
1148
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001149 mctl_phy_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001150
1151 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
1152
1153 return true;
1154}
1155
Andre Przywara161812c2023-06-07 01:07:43 +01001156static bool mctl_ctrl_init(const struct dram_para *para,
1157 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001158{
1159 struct sunxi_mctl_com_reg * const mctl_com =
1160 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
1161 struct sunxi_mctl_ctl_reg * const mctl_ctl =
1162 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
1163 u32 reg_val;
1164
1165 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
1166 writel(0x8000, &mctl_ctl->clken);
1167
1168 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1169
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001170 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
1171 writel(1, SUNXI_DRAM_COM_BASE + 0x50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001172 clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
1173
1174 writel(0, &mctl_ctl->hwlpctl);
1175
1176 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1177
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001178 reg_val = MSTR_ACTIVE_RANKS(config->ranks);
1179 switch (para->type) {
1180 case SUNXI_DRAM_TYPE_DDR3:
1181 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
1182 break;
1183 case SUNXI_DRAM_TYPE_LPDDR3:
1184 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_LPDDR3;
1185 break;
1186 case SUNXI_DRAM_TYPE_LPDDR4:
1187 reg_val |= MSTR_BURST_LENGTH(16) | MSTR_DEVICETYPE_LPDDR4;
1188 break;
1189 case SUNXI_DRAM_TYPE_DDR4:
1190 default:
1191 panic("This DRAM setup is currently not supported.\n");
1192 };
Andre Przywara161812c2023-06-07 01:07:43 +01001193 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001194 reg_val |= MSTR_BUSWIDTH_FULL;
1195 else
1196 reg_val |= MSTR_BUSWIDTH_HALF;
1197 writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
1198
Andre Przywara161812c2023-06-07 01:07:43 +01001199 if (config->ranks == 2)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001200 writel(0x0303, &mctl_ctl->odtmap);
1201 else
1202 writel(0x0201, &mctl_ctl->odtmap);
1203
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001204 switch (para->type) {
1205 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001206 reg_val = 0x06000400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001207 break;
1208 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001209 reg_val = 0x09020400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001210 break;
1211 case SUNXI_DRAM_TYPE_LPDDR4:
1212 reg_val = 0x04000400;
1213 break;
1214 case SUNXI_DRAM_TYPE_DDR4:
1215 default:
1216 panic("This DRAM setup is currently not supported.\n");
1217 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001218 writel(reg_val, &mctl_ctl->odtcfg);
1219 writel(reg_val, &mctl_ctl->unk_0x2240);
1220 writel(reg_val, &mctl_ctl->unk_0x3240);
1221 writel(reg_val, &mctl_ctl->unk_0x4240);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001222
Jernej Skrabec472d4042023-04-10 10:21:10 +02001223 writel(BIT(31), &mctl_com->cr);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001224
Andre Przywara161812c2023-06-07 01:07:43 +01001225 mctl_set_addrmap(config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001226
1227 mctl_set_timing_params(para);
1228
1229 writel(0, &mctl_ctl->pwrctl);
1230
1231 setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
1232 setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
1233 setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
1234 setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
1235 setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
1236
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001237 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
1238 setbits_le32(&mctl_ctl->dbictl, 0x1);
1239
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001240 setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1241 clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
1242
1243 writel(0, &mctl_com->maer0);
1244 writel(0, &mctl_com->maer1);
1245 writel(0, &mctl_com->maer2);
1246
1247 writel(0x20, &mctl_ctl->pwrctl);
1248 setbits_le32(&mctl_ctl->clken, BIT(8));
1249
1250 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
1251 /* this write seems to enable PHY MMIO region */
1252 setbits_le32(&mctl_com->unk_0x500, BIT(24));
1253
Andre Przywara161812c2023-06-07 01:07:43 +01001254 if (!mctl_phy_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001255 return false;
1256
1257 writel(0, &mctl_ctl->swctl);
1258 clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1259
1260 setbits_le32(&mctl_com->unk_0x014, BIT(31));
1261 writel(0xffffffff, &mctl_com->maer0);
1262 writel(0x7ff, &mctl_com->maer1);
1263 writel(0xffff, &mctl_com->maer2);
1264
1265 writel(1, &mctl_ctl->swctl);
1266 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1267
1268 return true;
1269}
1270
Andre Przywara161812c2023-06-07 01:07:43 +01001271static bool mctl_core_init(const struct dram_para *para,
1272 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001273{
Andre Przywaraa21a22c2023-06-07 01:07:42 +01001274 mctl_sys_init(para->clk);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001275
Andre Przywara161812c2023-06-07 01:07:43 +01001276 return mctl_ctrl_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001277}
1278
Andre Przywara161812c2023-06-07 01:07:43 +01001279static void mctl_auto_detect_rank_width(const struct dram_para *para,
1280 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001281{
1282 /* this is minimum size that it's supported */
Andre Przywara161812c2023-06-07 01:07:43 +01001283 config->cols = 8;
1284 config->rows = 13;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001285
1286 /*
1287 * Strategy here is to test most demanding combination first and least
1288 * demanding last, otherwise HW might not be fully utilized. For
1289 * example, half bus width and rank = 1 combination would also work
1290 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
1291 * visible.
1292 */
1293
1294 debug("testing 32-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001295 config->bus_full_width = 1;
1296 config->ranks = 2;
1297 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001298 return;
1299
1300 debug("testing 32-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001301 config->bus_full_width = 1;
1302 config->ranks = 1;
1303 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001304 return;
1305
1306 debug("testing 16-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001307 config->bus_full_width = 0;
1308 config->ranks = 2;
1309 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001310 return;
1311
1312 debug("testing 16-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001313 config->bus_full_width = 0;
1314 config->ranks = 1;
1315 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001316 return;
1317
1318 panic("This DRAM setup is currently not supported.\n");
1319}
1320
Andre Przywara161812c2023-06-07 01:07:43 +01001321static void mctl_auto_detect_dram_size(const struct dram_para *para,
1322 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001323{
1324 /* detect row address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001325 config->cols = 8;
1326 config->rows = 18;
1327 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001328
Andre Przywara161812c2023-06-07 01:07:43 +01001329 for (config->rows = 13; config->rows < 18; config->rows++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001330 /* 8 banks, 8 bit per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001331 if (mctl_mem_matches((1 << (config->rows + config->cols +
1332 4 + config->bus_full_width))))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001333 break;
1334 }
1335
1336 /* detect column address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001337 config->cols = 11;
1338 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001339
Andre Przywara161812c2023-06-07 01:07:43 +01001340 for (config->cols = 8; config->cols < 11; config->cols++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001341 /* 8 bits per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001342 if (mctl_mem_matches(1 << (config->cols + 1 +
1343 config->bus_full_width)))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001344 break;
1345 }
1346}
1347
Andre Przywara161812c2023-06-07 01:07:43 +01001348static unsigned long mctl_calc_size(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001349{
Andre Przywara161812c2023-06-07 01:07:43 +01001350 u8 width = config->bus_full_width ? 4 : 2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001351
1352 /* 8 banks */
Andre Przywara161812c2023-06-07 01:07:43 +01001353 return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001354}
1355
Andre Przywara161812c2023-06-07 01:07:43 +01001356static const struct dram_para para = {
1357 .clk = CONFIG_DRAM_CLK,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001358#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Andre Przywara161812c2023-06-07 01:07:43 +01001359 .type = SUNXI_DRAM_TYPE_DDR3,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001360#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
1361 .type = SUNXI_DRAM_TYPE_LPDDR3,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001362#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
1363 .type = SUNXI_DRAM_TYPE_LPDDR4,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001364#endif
Andre Przywara161812c2023-06-07 01:07:43 +01001365 .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
1366 .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
1367 .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
1368 .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
1369 .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
1370 .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001371 .tpr6 = CONFIG_DRAM_SUN50I_H616_TPR6,
Andre Przywara161812c2023-06-07 01:07:43 +01001372 .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
1373 .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
1374 .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
1375};
1376
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001377unsigned long sunxi_dram_init(void)
1378{
Jernej Skrabece04cd492022-01-30 15:27:13 +01001379 struct sunxi_prcm_reg *const prcm =
1380 (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +01001381 struct dram_config config;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001382 unsigned long size;
1383
Jernej Skrabece04cd492022-01-30 15:27:13 +01001384 setbits_le32(&prcm->res_cal_ctrl, BIT(8));
1385 clrbits_le32(&prcm->ohms240, 0x3f);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001386
Andre Przywara161812c2023-06-07 01:07:43 +01001387 mctl_auto_detect_rank_width(&para, &config);
1388 mctl_auto_detect_dram_size(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001389
Andre Przywara161812c2023-06-07 01:07:43 +01001390 mctl_core_init(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001391
Andre Przywara161812c2023-06-07 01:07:43 +01001392 size = mctl_calc_size(&config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001393
1394 mctl_set_master_priority();
1395
1396 return size;
1397};