blob: 35405915e9ab850a7c5e2a37d0c12de3806c30ee [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
Chris Morgan73375882024-08-30 10:55:07 -0500228#ifdef CONFIG_DRAM_SUN50I_H616_PHY_ADDR_MAP_1
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100229static const u8 phy_init[] = {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100230#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Chris Morgan73375882024-08-30 10:55:07 -0500231 0x08, 0x02, 0x12, 0x05, 0x15, 0x17, 0x18, 0x0b,
232 0x14, 0x07, 0x04, 0x13, 0x0c, 0x00, 0x16, 0x1a,
233 0x0a, 0x11, 0x03, 0x10, 0x0e, 0x01, 0x0d, 0x19,
234 0x06, 0x09, 0x0f
235#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
236 0x18, 0x00, 0x04, 0x09, 0x06, 0x05, 0x02, 0x19,
237 0x17, 0x03, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
238 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07,
239 0x08, 0x01, 0x1a
240#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
241 0x03, 0x00, 0x17, 0x05, 0x02, 0x19, 0x06, 0x07,
242 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
243 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x01,
244 0x18, 0x04, 0x1a
245#endif
246};
247#else /* CONFIG_DRAM_SUN50I_H616_PHY_ADDR_MAP_0 */
248static const u8 phy_init[] = {
249#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100250 0x07, 0x0b, 0x02, 0x16, 0x0d, 0x0e, 0x14, 0x19,
251 0x0a, 0x15, 0x03, 0x13, 0x04, 0x0c, 0x10, 0x06,
252 0x0f, 0x11, 0x1a, 0x01, 0x12, 0x17, 0x00, 0x08,
253 0x09, 0x05, 0x18
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100254#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
255 0x18, 0x06, 0x00, 0x05, 0x04, 0x03, 0x09, 0x02,
256 0x08, 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
257 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07,
258 0x17, 0x19, 0x1a
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300259#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
260 0x02, 0x00, 0x17, 0x05, 0x04, 0x19, 0x06, 0x07,
261 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
262 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x01,
263 0x18, 0x03, 0x1a
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100264#endif
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100265};
Chris Morgan73375882024-08-30 10:55:07 -0500266#endif /* CONFIG_DRAM_SUN50I_H616_PHY_ADDR_MAP_0 */
Andre Przywara1af6f152023-09-07 20:38:46 +0100267#define MASK_BYTE(reg, nr) (((reg) >> ((nr) * 8)) & 0x1f)
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100268static void mctl_phy_configure_odt(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100269{
Andre Przywara1af6f152023-09-07 20:38:46 +0100270 uint32_t val_lo, val_hi;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100271
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300272 /*
273 * This part should be applicable to all memory types, but is
274 * usually found in LPDDR4 bootloaders. Therefore, we will leave
275 * only for this type of memory.
276 */
277 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
278 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x390, BIT(5), BIT(4));
279 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3d0, BIT(5), BIT(4));
280 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x410, BIT(5), BIT(4));
281 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x450, BIT(5), BIT(4));
282 }
283
Andre Przywara1af6f152023-09-07 20:38:46 +0100284 val_lo = para->dx_dri;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300285 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0x04040404 : para->dx_dri;
Andre Przywara1af6f152023-09-07 20:38:46 +0100286 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x388);
287 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x38c);
288 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c8);
289 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3cc);
290 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x408);
291 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x40c);
292 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x448);
293 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x44c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100294
Andre Przywara1af6f152023-09-07 20:38:46 +0100295 val_lo = para->ca_dri;
296 val_hi = para->ca_dri;
297 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x340);
298 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x344);
299 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x348);
300 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x34c);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200301
Andre Przywara1af6f152023-09-07 20:38:46 +0100302 val_lo = (para->type == SUNXI_DRAM_TYPE_LPDDR3) ? 0 : para->dx_odt;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300303 val_hi = (para->type == SUNXI_DRAM_TYPE_LPDDR4) ? 0 : para->dx_odt;
Andre Przywara1af6f152023-09-07 20:38:46 +0100304 writel_relaxed(MASK_BYTE(val_lo, 0), SUNXI_DRAM_PHY0_BASE + 0x380);
305 writel_relaxed(MASK_BYTE(val_hi, 0), SUNXI_DRAM_PHY0_BASE + 0x384);
306 writel_relaxed(MASK_BYTE(val_lo, 1), SUNXI_DRAM_PHY0_BASE + 0x3c0);
307 writel_relaxed(MASK_BYTE(val_hi, 1), SUNXI_DRAM_PHY0_BASE + 0x3c4);
308 writel_relaxed(MASK_BYTE(val_lo, 2), SUNXI_DRAM_PHY0_BASE + 0x400);
309 writel_relaxed(MASK_BYTE(val_hi, 2), SUNXI_DRAM_PHY0_BASE + 0x404);
310 writel_relaxed(MASK_BYTE(val_lo, 3), SUNXI_DRAM_PHY0_BASE + 0x440);
311 writel_relaxed(MASK_BYTE(val_hi, 3), SUNXI_DRAM_PHY0_BASE + 0x444);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100312
313 dmb();
314}
315
Jernej Skrabecd74e0e72024-08-30 10:55:06 -0500316static bool mctl_phy_write_leveling(const struct dram_para *para,
317 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100318{
319 bool result = true;
320 u32 val;
321
322 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x80);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -0500323
324 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
325 /* MR2 value */
326 writel(0x1b, SUNXI_DRAM_PHY0_BASE + 0xc);
327 writel(0, SUNXI_DRAM_PHY0_BASE + 0x10);
328 } else {
329 writel(4, SUNXI_DRAM_PHY0_BASE + 0xc);
330 writel(0x40, SUNXI_DRAM_PHY0_BASE + 0x10);
331 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100332
333 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
334
Andre Przywara161812c2023-06-07 01:07:43 +0100335 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100336 val = 0xf;
337 else
338 val = 3;
339
Jernej Skrabec5a088482023-04-10 10:21:11 +0200340 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100341
342 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
343
344 val = readl(SUNXI_DRAM_PHY0_BASE + 0x258);
345 if (val == 0 || val == 0x3f)
346 result = false;
347 val = readl(SUNXI_DRAM_PHY0_BASE + 0x25c);
348 if (val == 0 || val == 0x3f)
349 result = false;
350 val = readl(SUNXI_DRAM_PHY0_BASE + 0x318);
351 if (val == 0 || val == 0x3f)
352 result = false;
353 val = readl(SUNXI_DRAM_PHY0_BASE + 0x31c);
354 if (val == 0 || val == 0x3f)
355 result = false;
356
357 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
358
Andre Przywara161812c2023-06-07 01:07:43 +0100359 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100360 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
361
362 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
363
Andre Przywara161812c2023-06-07 01:07:43 +0100364 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100365 val = 0xf;
366 else
367 val = 3;
368
Jernej Skrabec5a088482023-04-10 10:21:11 +0200369 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100370
371 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
372 }
373
374 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
375
376 return result;
377}
378
Andre Przywara161812c2023-06-07 01:07:43 +0100379static bool mctl_phy_read_calibration(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100380{
381 bool result = true;
382 u32 val, tmp;
383
384 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
385
386 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
387
Andre Przywara161812c2023-06-07 01:07:43 +0100388 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100389 val = 0xf;
390 else
391 val = 3;
392
393 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
394 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
395 result = false;
396 break;
397 }
398 }
399
400 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
401
402 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
403
Andre Przywara161812c2023-06-07 01:07:43 +0100404 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100405 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
406
407 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
408
409 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
410 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
411 result = false;
412 break;
413 }
414 }
415
Jernej Skrabec4e048422022-01-29 16:58:43 +0100416 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100417 }
418
419 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
420
421 val = readl(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
422 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
423 if (val < tmp)
424 val = tmp;
425 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
426 if (val < tmp)
427 val = tmp;
428 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
429 if (val < tmp)
430 val = tmp;
431 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
432
433 setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
434
435 return result;
436}
437
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300438static bool mctl_phy_read_training(const struct dram_para *para,
439 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100440{
441 u32 val1, val2, *ptr1, *ptr2;
442 bool result = true;
443 int i;
444
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300445 if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
446 writel(0, SUNXI_DRAM_PHY0_BASE + 0x800);
447 writel(0, SUNXI_DRAM_PHY0_BASE + 0x81c);
448 }
449
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100450 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
451 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x804, 0x3f, 0xf);
452 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x808, 0x3f, 0xf);
453 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa04, 0x3f, 0xf);
454 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa08, 0x3f, 0xf);
455
456 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
457 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
458
Jernej Skrabec5a088482023-04-10 10:21:11 +0200459 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100460 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
461 result = false;
462
Andre Przywara161812c2023-06-07 01:07:43 +0100463 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200464 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100465 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
466 result = false;
467 }
468
Jernej Skrabec5a088482023-04-10 10:21:11 +0200469 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x898);
470 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x850);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100471 for (i = 0; i < 9; i++) {
472 val1 = readl(&ptr1[i]);
473 val2 = readl(&ptr2[i]);
474 if (val1 - val2 <= 6)
475 result = false;
476 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200477 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
478 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x874);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100479 for (i = 0; i < 9; i++) {
480 val1 = readl(&ptr1[i]);
481 val2 = readl(&ptr2[i]);
482 if (val1 - val2 <= 6)
483 result = false;
484 }
485
Andre Przywara161812c2023-06-07 01:07:43 +0100486 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200487 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
488 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100489 for (i = 0; i < 9; i++) {
490 val1 = readl(&ptr1[i]);
491 val2 = readl(&ptr2[i]);
492 if (val1 - val2 <= 6)
493 result = false;
494 }
495
Jernej Skrabec5a088482023-04-10 10:21:11 +0200496 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xabc);
497 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100498 for (i = 0; i < 9; i++) {
499 val1 = readl(&ptr1[i]);
500 val2 = readl(&ptr2[i]);
501 if (val1 - val2 <= 6)
502 result = false;
503 }
504 }
505
506 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
507
Andre Przywara161812c2023-06-07 01:07:43 +0100508 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100509 /* maybe last parameter should be 1? */
510 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
511
512 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
513 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
514
Jernej Skrabec5a088482023-04-10 10:21:11 +0200515 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100516 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
517 result = false;
518
Andre Przywara161812c2023-06-07 01:07:43 +0100519 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200520 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100521 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
522 result = false;
523 }
524
525 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
526 }
527
528 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3);
529
530 return result;
531}
532
Andre Przywara161812c2023-06-07 01:07:43 +0100533static bool mctl_phy_write_training(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100534{
535 u32 val1, val2, *ptr1, *ptr2;
536 bool result = true;
537 int i;
538
539 writel(0, SUNXI_DRAM_PHY0_BASE + 0x134);
540 writel(0, SUNXI_DRAM_PHY0_BASE + 0x138);
541 writel(0, SUNXI_DRAM_PHY0_BASE + 0x19c);
542 writel(0, SUNXI_DRAM_PHY0_BASE + 0x1a0);
543
544 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 8);
545
546 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
547 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
548
Jernej Skrabec5a088482023-04-10 10:21:11 +0200549 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100550 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
551 result = false;
552
Andre Przywara161812c2023-06-07 01:07:43 +0100553 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200554 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100555 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
556 result = false;
557 }
558
Jernej Skrabec5a088482023-04-10 10:21:11 +0200559 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x938);
560 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
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 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200567 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x95c);
568 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x914);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100569 for (i = 0; i < 9; i++) {
570 val1 = readl(&ptr1[i]);
571 val2 = readl(&ptr2[i]);
572 if (val1 - val2 <= 6)
573 result = false;
574 }
575
Andre Przywara161812c2023-06-07 01:07:43 +0100576 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200577 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
578 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100579 for (i = 0; i < 9; i++) {
580 val1 = readl(&ptr1[i]);
581 val2 = readl(&ptr2[i]);
582 if (val1 - val2 <= 6)
583 result = false;
584 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200585 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
586 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100587 for (i = 0; i < 9; i++) {
588 val1 = readl(&ptr1[i]);
589 val2 = readl(&ptr2[i]);
590 if (val1 - val2 <= 6)
591 result = false;
592 }
593 }
594
595 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
596
Andre Przywara161812c2023-06-07 01:07:43 +0100597 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100598 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
599
600 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
601 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
602
Jernej Skrabec5a088482023-04-10 10:21:11 +0200603 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100604 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
605 result = false;
606
Andre Przywara161812c2023-06-07 01:07:43 +0100607 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200608 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100609 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
610 result = false;
611 }
612
613 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
614 }
615
616 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc);
617
618 return result;
619}
620
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100621static void mctl_phy_bit_delay_compensation(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100622{
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200623 u32 *ptr, val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100624 int i;
625
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200626 if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
627 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
628 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
629 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300630 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
631 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4, 0x80);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100632
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200633 if (para->tpr10 & BIT(30))
634 val = para->tpr11 & 0x3f;
635 else
636 val = (para->tpr11 & 0xf) << 1;
637
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200638 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484);
639 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200640 writel_relaxed(val, ptr);
641 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200642 ptr += 2;
643 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200644
645 if (para->tpr10 & BIT(30))
646 val = (para->odt_en >> 15) & 0x1e;
647 else
648 val = (para->tpr11 >> 15) & 0x1e;
649
650 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4d0);
651 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x590);
652 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4cc);
653 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x58c);
654
655 if (para->tpr10 & BIT(30))
656 val = (para->tpr11 >> 8) & 0x3f;
657 else
658 val = (para->tpr11 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100659
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200660 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
661 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200662 writel_relaxed(val, ptr);
663 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200664 ptr += 2;
665 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200666
667 if (para->tpr10 & BIT(30))
668 val = (para->odt_en >> 19) & 0x1e;
669 else
670 val = (para->tpr11 >> 19) & 0x1e;
671
672 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x524);
673 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e4);
674 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x520);
675 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e0);
676
677 if (para->tpr10 & BIT(30))
678 val = (para->tpr11 >> 16) & 0x3f;
679 else
680 val = (para->tpr11 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100681
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200682 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604);
683 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200684 writel_relaxed(val, ptr);
685 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200686 ptr += 2;
687 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200688
689 if (para->tpr10 & BIT(30))
690 val = (para->odt_en >> 23) & 0x1e;
691 else
692 val = (para->tpr11 >> 23) & 0x1e;
693
694 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x650);
695 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x710);
696 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x64c);
697 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x70c);
698
699 if (para->tpr10 & BIT(30))
700 val = (para->tpr11 >> 24) & 0x3f;
701 else
702 val = (para->tpr11 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100703
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200704 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658);
705 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200706 writel_relaxed(val, ptr);
707 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200708 ptr += 2;
709 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200710
711 if (para->tpr10 & BIT(30))
712 val = (para->odt_en >> 27) & 0x1e;
713 else
714 val = (para->tpr11 >> 27) & 0x1e;
715
716 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a4);
717 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x764);
718 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a0);
719 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x760);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100720
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200721 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100722
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200723 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
724 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100725
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200726 if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
727 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
728 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100729
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200730 if (para->tpr10 & BIT(30))
731 val = para->tpr12 & 0x3f;
732 else
733 val = (para->tpr12 & 0xf) << 1;
734
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200735 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480);
736 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200737 writel_relaxed(val, ptr);
738 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200739 ptr += 2;
740 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200741
742 if (para->tpr10 & BIT(30))
743 val = (para->odt_en << 1) & 0x1e;
744 else
745 val = (para->tpr12 >> 15) & 0x1e;
746
747 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x528);
748 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e8);
749 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4c8);
750 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x588);
751
752 if (para->tpr10 & BIT(30))
753 val = (para->tpr12 >> 8) & 0x3f;
754 else
755 val = (para->tpr12 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100756
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200757 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
758 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200759 writel_relaxed(val, ptr);
760 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200761 ptr += 2;
762 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200763
764 if (para->tpr10 & BIT(30))
765 val = (para->odt_en >> 3) & 0x1e;
766 else
767 val = (para->tpr12 >> 19) & 0x1e;
768
769 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x52c);
770 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5ec);
771 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x51c);
772 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5dc);
773
774 if (para->tpr10 & BIT(30))
775 val = (para->tpr12 >> 16) & 0x3f;
776 else
777 val = (para->tpr12 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100778
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200779 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600);
780 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200781 writel_relaxed(val, ptr);
782 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200783 ptr += 2;
784 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200785
786 if (para->tpr10 & BIT(30))
787 val = (para->odt_en >> 7) & 0x1e;
788 else
789 val = (para->tpr12 >> 23) & 0x1e;
790
791 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a8);
792 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x768);
793 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x648);
794 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x708);
795
796 if (para->tpr10 & BIT(30))
797 val = (para->tpr12 >> 24) & 0x3f;
798 else
799 val = (para->tpr12 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100800
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200801 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
802 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200803 writel_relaxed(val, ptr);
804 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200805 ptr += 2;
806 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200807
808 if (para->tpr10 & BIT(30))
809 val = (para->odt_en >> 11) & 0x1e;
810 else
811 val = (para->tpr12 >> 27) & 0x1e;
812
813 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6ac);
814 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x76c);
815 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x69c);
816 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x75c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100817
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200818 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100819
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200820 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
821 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100822}
823
Andre Przywara161812c2023-06-07 01:07:43 +0100824static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para,
825 const struct dram_config *config)
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200826{
827 u32 val, *ptr;
828 int i;
829
830 if (para->tpr0 & BIT(30))
831 val = (para->tpr0 >> 7) & 0x3e;
832 else
833 val = (para->tpr10 >> 3) & 0x1e;
834
835 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
836 for (i = 0; i < 32; i++)
837 writel(val, &ptr[i]);
838
839 val = (para->tpr10 << 1) & 0x1e;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200840 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200841 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
842 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200843 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200844
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300845 val = (para->tpr10 >> 7) & 0x1e;
846 switch (para->type) {
847 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100848 if (para->tpr2 & 1) {
849 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
850 if (config->ranks == 2) {
851 val = (para->tpr10 >> 11) & 0x1e;
852 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
853 }
854 if (para->tpr0 & BIT(31)) {
855 val = (para->tpr0 << 1) & 0x3e;
856 writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
857 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
858 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
859 }
860 } else {
861 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
862 if (config->ranks == 2) {
863 val = (para->tpr10 >> 11) & 0x1e;
864 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
865 }
866 if (para->tpr0 & BIT(31)) {
867 val = (para->tpr0 << 1) & 0x3e;
868 writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
869 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
870 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
871 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200872 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300873 break;
874 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100875 if (para->tpr2 & 1) {
876 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a0);
877 if (config->ranks == 2) {
878 val = (para->tpr10 >> 11) & 0x1e;
879 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
880 }
881 } else {
882 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e8);
883 if (config->ranks == 2) {
884 val = (para->tpr10 >> 11) & 0x1e;
885 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f8);
886 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200887 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300888 break;
889 case SUNXI_DRAM_TYPE_LPDDR4:
Jernej Skrabecd74e0e72024-08-30 10:55:06 -0500890 writel(val, SUNXI_DRAM_PHY0_BASE + 0x788);
891 if (config->ranks == 2) {
892 val = (para->tpr10 >> 11) & 0x1e;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300893 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
894 };
895 break;
896 case SUNXI_DRAM_TYPE_DDR4:
897 default:
898 panic("This DRAM setup is currently not supported.\n");
899 };
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200900}
901
Andre Przywara161812c2023-06-07 01:07:43 +0100902static bool mctl_phy_init(const struct dram_para *para,
903 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100904{
905 struct sunxi_mctl_com_reg * const mctl_com =
906 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
907 struct sunxi_mctl_ctl_reg * const mctl_ctl =
908 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200909 u32 val, val2, *ptr, mr0, mr2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100910 int i;
911
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300912 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
913 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4,0x80);
914
Andre Przywara161812c2023-06-07 01:07:43 +0100915 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100916 val = 0xf;
917 else
918 val = 3;
919 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
920
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300921 switch (para->type) {
922 case SUNXI_DRAM_TYPE_DDR3:
923 if (para->tpr2 & 0x100) {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100924 val = 9;
925 val2 = 7;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300926 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100927 val = 13;
928 val2 = 9;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300929 }
930 break;
931 case SUNXI_DRAM_TYPE_LPDDR3:
932 if (para->tpr2 & 0x100) {
933 val = 12;
934 val2 = 6;
935 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100936 val = 14;
937 val2 = 8;
938 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300939 break;
940 case SUNXI_DRAM_TYPE_LPDDR4:
941 val = 20;
942 val2 = 10;
943 break;
944 case SUNXI_DRAM_TYPE_DDR4:
945 default:
946 panic("This DRAM setup is currently not supported.\n");
947 };
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200948
949 writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
950 writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
951 writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
952 writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100953
954 writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
955 writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
956 writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
957 writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
958
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200959 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
960 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
961 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
962 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100963
Jernej Skrabec5a088482023-04-10 10:21:11 +0200964 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100965 for (i = 0; i < ARRAY_SIZE(phy_init); i++)
966 writel(phy_init[i], &ptr[i]);
967
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200968 if (para->tpr10 & TPR10_CA_BIT_DELAY)
Andre Przywara161812c2023-06-07 01:07:43 +0100969 mctl_phy_ca_bit_delay_compensation(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100970
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300971 switch (para->type) {
972 case SUNXI_DRAM_TYPE_DDR3:
973 val = para->tpr6 & 0xff;
974 break;
975 case SUNXI_DRAM_TYPE_LPDDR3:
976 val = para->tpr6 >> 8 & 0xff;
977 break;
978 case SUNXI_DRAM_TYPE_LPDDR4:
979 val = para->tpr6 >> 24 & 0xff;
980 break;
981 case SUNXI_DRAM_TYPE_DDR4:
982 default:
983 panic("This DRAM setup is currently not supported.\n");
984 };
985
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100986 writel(val, SUNXI_DRAM_PHY0_BASE + 0x3dc);
987 writel(val, SUNXI_DRAM_PHY0_BASE + 0x45c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100988
Jernej Skrabec64712da2023-04-10 10:21:14 +0200989 mctl_phy_configure_odt(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100990
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300991 switch (para->type) {
992 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100993 val = 0x0a;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300994 break;
995 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100996 val = 0x0b;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +0300997 break;
998 case SUNXI_DRAM_TYPE_LPDDR4:
999 val = 0x0d;
1000 break;
1001 case SUNXI_DRAM_TYPE_DDR4:
1002 default:
1003 panic("This DRAM setup is currently not supported.\n");
1004 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001005 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x7, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001006
1007 if (para->clk <= 672)
1008 writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
1009 if (para->clk > 500) {
1010 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
1011 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
1012 } else {
1013 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
1014 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
1015 }
1016
Jernej Skrabece96bafe2024-08-30 10:55:08 -05001017 clrbits_le32(&mctl_com->unk_0x500, 0x200);
1018 udelay(1);
1019
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001020 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
1021
Jernej Skrabec5a088482023-04-10 10:21:11 +02001022 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001023
Jernej Skrabece96bafe2024-08-30 10:55:08 -05001024 udelay(1000);
1025
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001026 writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001027
1028 writel(0, &mctl_ctl->swctl);
1029 setbits_le32(&mctl_ctl->dfimisc, 1);
1030
1031 /* start DFI init */
1032 setbits_le32(&mctl_ctl->dfimisc, 0x20);
1033 writel(1, &mctl_ctl->swctl);
1034 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1035 /* poll DFI init complete */
1036 mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
1037 writel(0, &mctl_ctl->swctl);
1038 clrbits_le32(&mctl_ctl->dfimisc, 0x20);
1039
1040 clrbits_le32(&mctl_ctl->pwrctl, 0x20);
1041 writel(1, &mctl_ctl->swctl);
1042 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1043 mctl_await_completion(&mctl_ctl->statr, 3, 1);
1044
Jernej Skrabece96bafe2024-08-30 10:55:08 -05001045 udelay(200);
1046
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001047 writel(0, &mctl_ctl->swctl);
1048 clrbits_le32(&mctl_ctl->dfimisc, 1);
1049
1050 writel(1, &mctl_ctl->swctl);
1051 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1052
Jernej Skrabecac8154d2023-04-10 10:21:19 +02001053 if (para->tpr2 & 0x100) {
1054 mr0 = 0x1b50;
1055 mr2 = 0x10;
1056 } else {
1057 mr0 = 0x1f14;
1058 mr2 = 0x20;
1059 }
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001060 switch (para->type) {
1061 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001062 writel(mr0, &mctl_ctl->mrctrl1);
1063 writel(0x80000030, &mctl_ctl->mrctrl0);
1064 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001065
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001066 writel(4, &mctl_ctl->mrctrl1);
1067 writel(0x80001030, &mctl_ctl->mrctrl0);
1068 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001069
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001070 writel(mr2, &mctl_ctl->mrctrl1);
1071 writel(0x80002030, &mctl_ctl->mrctrl0);
1072 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001073
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001074 writel(0, &mctl_ctl->mrctrl1);
1075 writel(0x80003030, &mctl_ctl->mrctrl0);
1076 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001077 break;
1078 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001079 writel(mr0, &mctl_ctl->mrctrl1);
1080 writel(0x800000f0, &mctl_ctl->mrctrl0);
1081 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1082
1083 writel(4, &mctl_ctl->mrctrl1);
1084 writel(0x800000f0, &mctl_ctl->mrctrl0);
1085 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1086
1087 writel(mr2, &mctl_ctl->mrctrl1);
1088 writel(0x800000f0, &mctl_ctl->mrctrl0);
1089 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1090
1091 writel(0x301, &mctl_ctl->mrctrl1);
1092 writel(0x800000f0, &mctl_ctl->mrctrl0);
1093 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001094 break;
1095 case SUNXI_DRAM_TYPE_LPDDR4:
1096 writel(0x0, &mctl_ctl->mrctrl1);
1097 writel(0x80000030, &mctl_ctl->mrctrl0);
1098 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1099
1100 writel(0x134, &mctl_ctl->mrctrl1);
1101 writel(0x80000030, &mctl_ctl->mrctrl0);
1102 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1103
1104 writel(0x21b, &mctl_ctl->mrctrl1);
1105 writel(0x80000030, &mctl_ctl->mrctrl0);
1106 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1107
1108 writel(0x333, &mctl_ctl->mrctrl1);
1109 writel(0x80000030, &mctl_ctl->mrctrl0);
1110 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1111
1112 writel(0x403, &mctl_ctl->mrctrl1);
1113 writel(0x80000030, &mctl_ctl->mrctrl0);
1114 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1115
1116 writel(0xb04, &mctl_ctl->mrctrl1);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001117 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001118 writel(0x80000030, &mctl_ctl->mrctrl0);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001119 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001120 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1121
1122 writel(0xc72, &mctl_ctl->mrctrl1);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001123 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001124 writel(0x80000030, &mctl_ctl->mrctrl0);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001125 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001126 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1127
1128 writel(0xe09, &mctl_ctl->mrctrl1);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001129 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001130 writel(0x80000030, &mctl_ctl->mrctrl0);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001131 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001132 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1133
1134 writel(0x1624, &mctl_ctl->mrctrl1);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001135 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001136 writel(0x80000030, &mctl_ctl->mrctrl0);
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001137 udelay(10);
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001138 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1139 break;
1140 case SUNXI_DRAM_TYPE_DDR4:
1141 default:
1142 panic("This DRAM setup is currently not supported.\n");
1143 };
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001144
1145 writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
1146
1147 writel(0, &mctl_ctl->swctl);
1148 clrbits_le32(&mctl_ctl->rfshctl3, 1);
1149 writel(1, &mctl_ctl->swctl);
1150
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001151 if (para->tpr10 & TPR10_WRITE_LEVELING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001152 for (i = 0; i < 5; i++)
Jernej Skrabecd74e0e72024-08-30 10:55:06 -05001153 if (mctl_phy_write_leveling(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001154 break;
1155 if (i == 5) {
1156 debug("write leveling failed!\n");
1157 return false;
1158 }
1159 }
1160
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001161 if (para->tpr10 & TPR10_READ_CALIBRATION) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001162 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001163 if (mctl_phy_read_calibration(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001164 break;
1165 if (i == 5) {
1166 debug("read calibration failed!\n");
1167 return false;
1168 }
1169 }
1170
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001171 if (para->tpr10 & TPR10_READ_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001172 for (i = 0; i < 5; i++)
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001173 if (mctl_phy_read_training(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001174 break;
1175 if (i == 5) {
1176 debug("read training failed!\n");
1177 return false;
1178 }
1179 }
1180
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001181 if (para->tpr10 & TPR10_WRITE_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001182 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001183 if (mctl_phy_write_training(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001184 break;
1185 if (i == 5) {
1186 debug("write training failed!\n");
1187 return false;
1188 }
1189 }
1190
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001191 mctl_phy_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001192
1193 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
1194
1195 return true;
1196}
1197
Andre Przywara161812c2023-06-07 01:07:43 +01001198static bool mctl_ctrl_init(const struct dram_para *para,
1199 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001200{
1201 struct sunxi_mctl_com_reg * const mctl_com =
1202 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
1203 struct sunxi_mctl_ctl_reg * const mctl_ctl =
1204 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
1205 u32 reg_val;
1206
1207 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
1208 writel(0x8000, &mctl_ctl->clken);
1209
1210 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1211
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001212 if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
1213 writel(1, SUNXI_DRAM_COM_BASE + 0x50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001214 clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
1215
1216 writel(0, &mctl_ctl->hwlpctl);
1217
1218 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1219
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001220 reg_val = MSTR_ACTIVE_RANKS(config->ranks);
1221 switch (para->type) {
1222 case SUNXI_DRAM_TYPE_DDR3:
1223 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
1224 break;
1225 case SUNXI_DRAM_TYPE_LPDDR3:
1226 reg_val |= MSTR_BURST_LENGTH(8) | MSTR_DEVICETYPE_LPDDR3;
1227 break;
1228 case SUNXI_DRAM_TYPE_LPDDR4:
1229 reg_val |= MSTR_BURST_LENGTH(16) | MSTR_DEVICETYPE_LPDDR4;
1230 break;
1231 case SUNXI_DRAM_TYPE_DDR4:
1232 default:
1233 panic("This DRAM setup is currently not supported.\n");
1234 };
Andre Przywara161812c2023-06-07 01:07:43 +01001235 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001236 reg_val |= MSTR_BUSWIDTH_FULL;
1237 else
1238 reg_val |= MSTR_BUSWIDTH_HALF;
1239 writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
1240
Andre Przywara161812c2023-06-07 01:07:43 +01001241 if (config->ranks == 2)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001242 writel(0x0303, &mctl_ctl->odtmap);
1243 else
1244 writel(0x0201, &mctl_ctl->odtmap);
1245
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001246 switch (para->type) {
1247 case SUNXI_DRAM_TYPE_DDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001248 reg_val = 0x06000400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001249 break;
1250 case SUNXI_DRAM_TYPE_LPDDR3:
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001251 reg_val = 0x09020400;
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001252 break;
1253 case SUNXI_DRAM_TYPE_LPDDR4:
1254 reg_val = 0x04000400;
1255 break;
1256 case SUNXI_DRAM_TYPE_DDR4:
1257 default:
1258 panic("This DRAM setup is currently not supported.\n");
1259 };
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001260 writel(reg_val, &mctl_ctl->odtcfg);
1261 writel(reg_val, &mctl_ctl->unk_0x2240);
1262 writel(reg_val, &mctl_ctl->unk_0x3240);
1263 writel(reg_val, &mctl_ctl->unk_0x4240);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001264
Jernej Skrabec472d4042023-04-10 10:21:10 +02001265 writel(BIT(31), &mctl_com->cr);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001266
Andre Przywara161812c2023-06-07 01:07:43 +01001267 mctl_set_addrmap(config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001268
1269 mctl_set_timing_params(para);
1270
1271 writel(0, &mctl_ctl->pwrctl);
1272
1273 setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
1274 setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
1275 setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
1276 setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
1277 setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
1278
1279 setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1280 clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
1281
1282 writel(0, &mctl_com->maer0);
1283 writel(0, &mctl_com->maer1);
1284 writel(0, &mctl_com->maer2);
1285
1286 writel(0x20, &mctl_ctl->pwrctl);
1287 setbits_le32(&mctl_ctl->clken, BIT(8));
1288
1289 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
Jernej Skrabece96bafe2024-08-30 10:55:08 -05001290 udelay(1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001291 /* this write seems to enable PHY MMIO region */
1292 setbits_le32(&mctl_com->unk_0x500, BIT(24));
Jernej Skrabece96bafe2024-08-30 10:55:08 -05001293 udelay(1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001294
Andre Przywara161812c2023-06-07 01:07:43 +01001295 if (!mctl_phy_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001296 return false;
1297
1298 writel(0, &mctl_ctl->swctl);
1299 clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1300
1301 setbits_le32(&mctl_com->unk_0x014, BIT(31));
1302 writel(0xffffffff, &mctl_com->maer0);
1303 writel(0x7ff, &mctl_com->maer1);
1304 writel(0xffff, &mctl_com->maer2);
1305
1306 writel(1, &mctl_ctl->swctl);
1307 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1308
1309 return true;
1310}
1311
Andre Przywara161812c2023-06-07 01:07:43 +01001312static bool mctl_core_init(const struct dram_para *para,
1313 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001314{
Andre Przywaraa21a22c2023-06-07 01:07:42 +01001315 mctl_sys_init(para->clk);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001316
Andre Przywara161812c2023-06-07 01:07:43 +01001317 return mctl_ctrl_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001318}
1319
Andre Przywara161812c2023-06-07 01:07:43 +01001320static void mctl_auto_detect_rank_width(const struct dram_para *para,
1321 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001322{
1323 /* this is minimum size that it's supported */
Andre Przywara161812c2023-06-07 01:07:43 +01001324 config->cols = 8;
1325 config->rows = 13;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001326
1327 /*
1328 * Strategy here is to test most demanding combination first and least
1329 * demanding last, otherwise HW might not be fully utilized. For
1330 * example, half bus width and rank = 1 combination would also work
1331 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
1332 * visible.
1333 */
1334
1335 debug("testing 32-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001336 config->bus_full_width = 1;
1337 config->ranks = 2;
1338 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001339 return;
1340
1341 debug("testing 32-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001342 config->bus_full_width = 1;
1343 config->ranks = 1;
1344 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001345 return;
1346
1347 debug("testing 16-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001348 config->bus_full_width = 0;
1349 config->ranks = 2;
1350 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001351 return;
1352
1353 debug("testing 16-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001354 config->bus_full_width = 0;
1355 config->ranks = 1;
1356 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001357 return;
1358
1359 panic("This DRAM setup is currently not supported.\n");
1360}
1361
Andre Przywara161812c2023-06-07 01:07:43 +01001362static void mctl_auto_detect_dram_size(const struct dram_para *para,
1363 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001364{
1365 /* detect row address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001366 config->cols = 8;
1367 config->rows = 18;
1368 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001369
Andre Przywara161812c2023-06-07 01:07:43 +01001370 for (config->rows = 13; config->rows < 18; config->rows++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001371 /* 8 banks, 8 bit per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001372 if (mctl_mem_matches((1 << (config->rows + config->cols +
1373 4 + config->bus_full_width))))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001374 break;
1375 }
1376
1377 /* detect column address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001378 config->cols = 11;
1379 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001380
Andre Przywara161812c2023-06-07 01:07:43 +01001381 for (config->cols = 8; config->cols < 11; config->cols++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001382 /* 8 bits per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001383 if (mctl_mem_matches(1 << (config->cols + 1 +
1384 config->bus_full_width)))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001385 break;
1386 }
1387}
1388
Andre Przywara161812c2023-06-07 01:07:43 +01001389static unsigned long mctl_calc_size(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001390{
Andre Przywara161812c2023-06-07 01:07:43 +01001391 u8 width = config->bus_full_width ? 4 : 2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001392
1393 /* 8 banks */
Andre Przywara161812c2023-06-07 01:07:43 +01001394 return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001395}
1396
Andre Przywara161812c2023-06-07 01:07:43 +01001397static const struct dram_para para = {
1398 .clk = CONFIG_DRAM_CLK,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001399#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Andre Przywara161812c2023-06-07 01:07:43 +01001400 .type = SUNXI_DRAM_TYPE_DDR3,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001401#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
1402 .type = SUNXI_DRAM_TYPE_LPDDR3,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001403#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR4)
1404 .type = SUNXI_DRAM_TYPE_LPDDR4,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001405#endif
Andre Przywara161812c2023-06-07 01:07:43 +01001406 .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
1407 .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
1408 .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
1409 .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
1410 .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
1411 .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
Mikhail Kalashnikov918be3a2023-11-11 12:10:00 +03001412 .tpr6 = CONFIG_DRAM_SUN50I_H616_TPR6,
Andre Przywara161812c2023-06-07 01:07:43 +01001413 .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
1414 .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
1415 .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
1416};
1417
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001418unsigned long sunxi_dram_init(void)
1419{
Jernej Skrabece04cd492022-01-30 15:27:13 +01001420 struct sunxi_prcm_reg *const prcm =
1421 (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +01001422 struct dram_config config;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001423 unsigned long size;
1424
Jernej Skrabece04cd492022-01-30 15:27:13 +01001425 setbits_le32(&prcm->res_cal_ctrl, BIT(8));
1426 clrbits_le32(&prcm->ohms240, 0x3f);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001427
Andre Przywara161812c2023-06-07 01:07:43 +01001428 mctl_auto_detect_rank_width(&para, &config);
1429 mctl_auto_detect_dram_size(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001430
Andre Przywara161812c2023-06-07 01:07:43 +01001431 mctl_core_init(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001432
Andre Przywara161812c2023-06-07 01:07:43 +01001433 size = mctl_calc_size(&config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001434
1435 mctl_set_master_priority();
1436
1437 return size;
1438};