blob: 7e580b62dcaea3c16f61ac3f966e4e625f129bec [file] [log] [blame]
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * sun50i H616 platform dram controller driver
4 *
5 * While controller is very similar to that in H6, PHY is completely
6 * unknown. That's why this driver has plenty of magic numbers. Some
7 * meaning was nevertheless deduced from strings found in boot0 and
8 * known meaning of some dram parameters.
9 * This driver only supports DDR3 memory and omits logic for all
10 * other supported types supported by hardware.
11 *
12 * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
13 *
14 */
15#include <common.h>
16#include <init.h>
17#include <log.h>
18#include <asm/io.h>
19#include <asm/arch/clock.h>
20#include <asm/arch/dram.h>
21#include <asm/arch/cpu.h>
Jernej Skrabece04cd492022-01-30 15:27:13 +010022#include <asm/arch/prcm.h>
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010023#include <linux/bitops.h>
24#include <linux/delay.h>
25#include <linux/kconfig.h>
26
27enum {
28 MBUS_QOS_LOWEST = 0,
29 MBUS_QOS_LOW,
30 MBUS_QOS_HIGH,
31 MBUS_QOS_HIGHEST
32};
33
Andre Przywara16f6f792023-06-07 01:07:41 +010034static void mbus_configure_port(u8 port,
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010035 bool bwlimit,
36 bool priority,
37 u8 qos,
38 u8 waittime,
39 u8 acs,
40 u16 bwl0,
41 u16 bwl1,
42 u16 bwl2)
43{
44 struct sunxi_mctl_com_reg * const mctl_com =
45 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
46
47 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
48 | (priority ? (1 << 1) : 0)
49 | ((qos & 0x3) << 2)
50 | ((waittime & 0xf) << 4)
51 | ((acs & 0xff) << 8)
52 | (bwl0 << 16) );
53 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
54
55 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
56 writel_relaxed(cfg0, &mctl_com->master[port].cfg0);
57 writel_relaxed(cfg1, &mctl_com->master[port].cfg1);
58}
59
60#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
61 mbus_configure_port(port, bwlimit, false, \
62 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
63
64static void mctl_set_master_priority(void)
65{
66 struct sunxi_mctl_com_reg * const mctl_com =
67 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
68
69 /* enable bandwidth limit windows and set windows size 1us */
70 writel(399, &mctl_com->tmr);
71 writel(BIT(16), &mctl_com->bwcr);
72
73 MBUS_CONF( 0, true, HIGHEST, 0, 256, 128, 100);
74 MBUS_CONF( 1, true, HIGH, 0, 1536, 1400, 256);
75 MBUS_CONF( 2, true, HIGHEST, 0, 512, 256, 96);
76 MBUS_CONF( 3, true, HIGH, 0, 256, 100, 80);
77 MBUS_CONF( 4, true, HIGH, 2, 8192, 5500, 5000);
78 MBUS_CONF( 5, true, HIGH, 2, 100, 64, 32);
79 MBUS_CONF( 6, true, HIGH, 2, 100, 64, 32);
80 MBUS_CONF( 8, true, HIGH, 0, 256, 128, 64);
81 MBUS_CONF(11, true, HIGH, 0, 256, 128, 100);
82 MBUS_CONF(14, true, HIGH, 0, 1024, 256, 64);
83 MBUS_CONF(16, true, HIGHEST, 6, 8192, 2800, 2400);
84 MBUS_CONF(21, true, HIGHEST, 6, 2048, 768, 512);
85 MBUS_CONF(25, true, HIGHEST, 0, 100, 64, 32);
86 MBUS_CONF(26, true, HIGH, 2, 8192, 5500, 5000);
87 MBUS_CONF(37, true, HIGH, 0, 256, 128, 64);
88 MBUS_CONF(38, true, HIGH, 2, 100, 64, 32);
89 MBUS_CONF(39, true, HIGH, 2, 8192, 5500, 5000);
90 MBUS_CONF(40, true, HIGH, 2, 100, 64, 32);
91
92 dmb();
93}
94
Andre Przywaraa21a22c2023-06-07 01:07:42 +010095static void mctl_sys_init(u32 clk_rate)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +010096{
97 struct sunxi_ccm_reg * const ccm =
98 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
99 struct sunxi_mctl_com_reg * const mctl_com =
100 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
101 struct sunxi_mctl_ctl_reg * const mctl_ctl =
102 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
103
104 /* Put all DRAM-related blocks to reset state */
105 clrbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
106 clrbits_le32(&ccm->mbus_cfg, MBUS_RESET);
107 clrbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
108 udelay(5);
109 clrbits_le32(&ccm->dram_gate_reset, BIT(RESET_SHIFT));
110 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
111 clrbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
112
113 udelay(5);
114
115 /* Set PLL5 rate to doubled DRAM clock rate */
116 writel(CCM_PLL5_CTRL_EN | CCM_PLL5_LOCK_EN | CCM_PLL5_OUT_EN |
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100117 CCM_PLL5_CTRL_N(clk_rate * 2 / 24), &ccm->pll5_cfg);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100118 mctl_await_completion(&ccm->pll5_cfg, CCM_PLL5_LOCK, CCM_PLL5_LOCK);
119
120 /* Configure DRAM mod clock */
121 writel(DRAM_CLK_SRC_PLL5, &ccm->dram_clk_cfg);
122 writel(BIT(RESET_SHIFT), &ccm->dram_gate_reset);
123 udelay(5);
124 setbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
125
126 /* Disable all channels */
127 writel(0, &mctl_com->maer0);
128 writel(0, &mctl_com->maer1);
129 writel(0, &mctl_com->maer2);
130
131 /* Configure MBUS and enable DRAM mod reset */
132 setbits_le32(&ccm->mbus_cfg, MBUS_RESET);
133 setbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
134
135 clrbits_le32(&mctl_com->unk_0x500, BIT(25));
136
137 setbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
138 udelay(5);
139
140 /* Unknown hack, which enables access of mctl_ctl regs */
141 writel(0x8000, &mctl_ctl->clken);
142}
143
Andre Przywara161812c2023-06-07 01:07:43 +0100144static void mctl_set_addrmap(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100145{
146 struct sunxi_mctl_ctl_reg * const mctl_ctl =
147 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +0100148 u8 cols = config->cols;
149 u8 rows = config->rows;
150 u8 ranks = config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100151
Andre Przywara161812c2023-06-07 01:07:43 +0100152 if (!config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100153 cols -= 1;
154
155 /* Ranks */
156 if (ranks == 2)
157 mctl_ctl->addrmap[0] = rows + cols - 3;
158 else
159 mctl_ctl->addrmap[0] = 0x1F;
160
161 /* Banks, hardcoded to 8 banks now */
162 mctl_ctl->addrmap[1] = (cols - 2) | (cols - 2) << 8 | (cols - 2) << 16;
163
164 /* Columns */
165 mctl_ctl->addrmap[2] = 0;
166 switch (cols) {
167 case 7:
168 mctl_ctl->addrmap[3] = 0x1F1F1F00;
169 mctl_ctl->addrmap[4] = 0x1F1F;
170 break;
171 case 8:
172 mctl_ctl->addrmap[3] = 0x1F1F0000;
173 mctl_ctl->addrmap[4] = 0x1F1F;
174 break;
175 case 9:
176 mctl_ctl->addrmap[3] = 0x1F000000;
177 mctl_ctl->addrmap[4] = 0x1F1F;
178 break;
179 case 10:
180 mctl_ctl->addrmap[3] = 0;
181 mctl_ctl->addrmap[4] = 0x1F1F;
182 break;
183 case 11:
184 mctl_ctl->addrmap[3] = 0;
185 mctl_ctl->addrmap[4] = 0x1F00;
186 break;
187 case 12:
188 mctl_ctl->addrmap[3] = 0;
189 mctl_ctl->addrmap[4] = 0;
190 break;
191 default:
192 panic("Unsupported DRAM configuration: column number invalid\n");
193 }
194
195 /* Rows */
196 mctl_ctl->addrmap[5] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
197 switch (rows) {
198 case 13:
199 mctl_ctl->addrmap[6] = (cols - 3) | 0x0F0F0F00;
200 mctl_ctl->addrmap[7] = 0x0F0F;
201 break;
202 case 14:
203 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | 0x0F0F0000;
204 mctl_ctl->addrmap[7] = 0x0F0F;
205 break;
206 case 15:
207 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | 0x0F000000;
208 mctl_ctl->addrmap[7] = 0x0F0F;
209 break;
210 case 16:
211 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
212 mctl_ctl->addrmap[7] = 0x0F0F;
213 break;
214 case 17:
215 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
216 mctl_ctl->addrmap[7] = (cols - 3) | 0x0F00;
217 break;
218 case 18:
219 mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
220 mctl_ctl->addrmap[7] = (cols - 3) | ((cols - 3) << 8);
221 break;
222 default:
223 panic("Unsupported DRAM configuration: row number invalid\n");
224 }
225
226 /* Bank groups, DDR4 only */
227 mctl_ctl->addrmap[8] = 0x3F3F;
228}
229
230static const u8 phy_init[] = {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100231#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100232 0x07, 0x0b, 0x02, 0x16, 0x0d, 0x0e, 0x14, 0x19,
233 0x0a, 0x15, 0x03, 0x13, 0x04, 0x0c, 0x10, 0x06,
234 0x0f, 0x11, 0x1a, 0x01, 0x12, 0x17, 0x00, 0x08,
235 0x09, 0x05, 0x18
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100236#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
237 0x18, 0x06, 0x00, 0x05, 0x04, 0x03, 0x09, 0x02,
238 0x08, 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
239 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x07,
240 0x17, 0x19, 0x1a
241#endif
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100242};
243
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100244static void mctl_phy_configure_odt(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100245{
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200246 unsigned int val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100247
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200248 val = para->dx_dri & 0x1f;
249 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x388);
250 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x38c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100251
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200252 val = (para->dx_dri >> 8) & 0x1f;
253 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c8);
254 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3cc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100255
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200256 val = (para->dx_dri >> 16) & 0x1f;
257 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x408);
258 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x40c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100259
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200260 val = (para->dx_dri >> 24) & 0x1f;
261 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x448);
262 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x44c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100263
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200264 val = para->ca_dri & 0x1f;
265 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x340);
266 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x344);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100267
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200268 val = (para->ca_dri >> 8) & 0x1f;
269 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x348);
270 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x34c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100271
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200272 val = para->dx_odt & 0x1f;
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100273 if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
274 writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x380);
275 else
276 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x380);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200277 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x384);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100278
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200279 val = (para->dx_odt >> 8) & 0x1f;
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100280 if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
281 writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x3c0);
282 else
283 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c0);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200284 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3c4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100285
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200286 val = (para->dx_odt >> 16) & 0x1f;
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100287 if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
288 writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x400);
289 else
290 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x400);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200291 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x404);
292
293 val = (para->dx_odt >> 24) & 0x1f;
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100294 if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
295 writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x440);
296 else
297 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x440);
Jernej Skrabecdd533da2023-04-10 10:21:12 +0200298 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x444);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100299
300 dmb();
301}
302
Andre Przywara161812c2023-06-07 01:07:43 +0100303static bool mctl_phy_write_leveling(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100304{
305 bool result = true;
306 u32 val;
307
308 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x80);
309 writel(4, SUNXI_DRAM_PHY0_BASE + 0xc);
310 writel(0x40, SUNXI_DRAM_PHY0_BASE + 0x10);
311
312 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
313
Andre Przywara161812c2023-06-07 01:07:43 +0100314 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100315 val = 0xf;
316 else
317 val = 3;
318
Jernej Skrabec5a088482023-04-10 10:21:11 +0200319 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100320
321 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
322
323 val = readl(SUNXI_DRAM_PHY0_BASE + 0x258);
324 if (val == 0 || val == 0x3f)
325 result = false;
326 val = readl(SUNXI_DRAM_PHY0_BASE + 0x25c);
327 if (val == 0 || val == 0x3f)
328 result = false;
329 val = readl(SUNXI_DRAM_PHY0_BASE + 0x318);
330 if (val == 0 || val == 0x3f)
331 result = false;
332 val = readl(SUNXI_DRAM_PHY0_BASE + 0x31c);
333 if (val == 0 || val == 0x3f)
334 result = false;
335
336 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
337
Andre Przywara161812c2023-06-07 01:07:43 +0100338 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100339 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
340
341 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
342
Andre Przywara161812c2023-06-07 01:07:43 +0100343 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100344 val = 0xf;
345 else
346 val = 3;
347
Jernej Skrabec5a088482023-04-10 10:21:11 +0200348 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100349
350 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
351 }
352
353 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
354
355 return result;
356}
357
Andre Przywara161812c2023-06-07 01:07:43 +0100358static bool mctl_phy_read_calibration(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100359{
360 bool result = true;
361 u32 val, tmp;
362
363 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
364
365 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
366
Andre Przywara161812c2023-06-07 01:07:43 +0100367 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100368 val = 0xf;
369 else
370 val = 3;
371
372 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
373 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
374 result = false;
375 break;
376 }
377 }
378
379 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
380
381 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
382
Andre Przywara161812c2023-06-07 01:07:43 +0100383 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100384 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
385
386 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
387
388 while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
389 if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
390 result = false;
391 break;
392 }
393 }
394
Jernej Skrabec4e048422022-01-29 16:58:43 +0100395 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100396 }
397
398 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
399
400 val = readl(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
401 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
402 if (val < tmp)
403 val = tmp;
404 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
405 if (val < tmp)
406 val = tmp;
407 tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
408 if (val < tmp)
409 val = tmp;
410 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
411
412 setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
413
414 return result;
415}
416
Andre Przywara161812c2023-06-07 01:07:43 +0100417static bool mctl_phy_read_training(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100418{
419 u32 val1, val2, *ptr1, *ptr2;
420 bool result = true;
421 int i;
422
423 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
424 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x804, 0x3f, 0xf);
425 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x808, 0x3f, 0xf);
426 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa04, 0x3f, 0xf);
427 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa08, 0x3f, 0xf);
428
429 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
430 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
431
Jernej Skrabec5a088482023-04-10 10:21:11 +0200432 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100433 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
434 result = false;
435
Andre Przywara161812c2023-06-07 01:07:43 +0100436 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200437 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100438 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
439 result = false;
440 }
441
Jernej Skrabec5a088482023-04-10 10:21:11 +0200442 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x898);
443 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x850);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100444 for (i = 0; i < 9; i++) {
445 val1 = readl(&ptr1[i]);
446 val2 = readl(&ptr2[i]);
447 if (val1 - val2 <= 6)
448 result = false;
449 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200450 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
451 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x874);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100452 for (i = 0; i < 9; i++) {
453 val1 = readl(&ptr1[i]);
454 val2 = readl(&ptr2[i]);
455 if (val1 - val2 <= 6)
456 result = false;
457 }
458
Andre Przywara161812c2023-06-07 01:07:43 +0100459 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200460 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
461 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100462 for (i = 0; i < 9; i++) {
463 val1 = readl(&ptr1[i]);
464 val2 = readl(&ptr2[i]);
465 if (val1 - val2 <= 6)
466 result = false;
467 }
468
Jernej Skrabec5a088482023-04-10 10:21:11 +0200469 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xabc);
470 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa74);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100471 for (i = 0; i < 9; i++) {
472 val1 = readl(&ptr1[i]);
473 val2 = readl(&ptr2[i]);
474 if (val1 - val2 <= 6)
475 result = false;
476 }
477 }
478
479 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
480
Andre Przywara161812c2023-06-07 01:07:43 +0100481 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100482 /* maybe last parameter should be 1? */
483 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
484
485 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
486 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
487
Jernej Skrabec5a088482023-04-10 10:21:11 +0200488 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100489 if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
490 result = false;
491
Andre Przywara161812c2023-06-07 01:07:43 +0100492 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200493 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100494 if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
495 result = false;
496 }
497
498 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
499 }
500
501 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3);
502
503 return result;
504}
505
Andre Przywara161812c2023-06-07 01:07:43 +0100506static bool mctl_phy_write_training(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100507{
508 u32 val1, val2, *ptr1, *ptr2;
509 bool result = true;
510 int i;
511
512 writel(0, SUNXI_DRAM_PHY0_BASE + 0x134);
513 writel(0, SUNXI_DRAM_PHY0_BASE + 0x138);
514 writel(0, SUNXI_DRAM_PHY0_BASE + 0x19c);
515 writel(0, SUNXI_DRAM_PHY0_BASE + 0x1a0);
516
517 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 8);
518
519 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
520 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
521
Jernej Skrabec5a088482023-04-10 10:21:11 +0200522 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100523 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
524 result = false;
525
Andre Przywara161812c2023-06-07 01:07:43 +0100526 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200527 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100528 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
529 result = false;
530 }
531
Jernej Skrabec5a088482023-04-10 10:21:11 +0200532 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x938);
533 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100534 for (i = 0; i < 9; i++) {
535 val1 = readl(&ptr1[i]);
536 val2 = readl(&ptr2[i]);
537 if (val1 - val2 <= 6)
538 result = false;
539 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200540 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x95c);
541 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x914);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100542 for (i = 0; i < 9; i++) {
543 val1 = readl(&ptr1[i]);
544 val2 = readl(&ptr2[i]);
545 if (val1 - val2 <= 6)
546 result = false;
547 }
548
Andre Przywara161812c2023-06-07 01:07:43 +0100549 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200550 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
551 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100552 for (i = 0; i < 9; i++) {
553 val1 = readl(&ptr1[i]);
554 val2 = readl(&ptr2[i]);
555 if (val1 - val2 <= 6)
556 result = false;
557 }
Jernej Skrabec5a088482023-04-10 10:21:11 +0200558 ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
559 ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb14);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100560 for (i = 0; i < 9; i++) {
561 val1 = readl(&ptr1[i]);
562 val2 = readl(&ptr2[i]);
563 if (val1 - val2 <= 6)
564 result = false;
565 }
566 }
567
568 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
569
Andre Przywara161812c2023-06-07 01:07:43 +0100570 if (config->ranks == 2) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100571 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
572
573 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
574 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
575
Jernej Skrabec5a088482023-04-10 10:21:11 +0200576 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100577 if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
578 result = false;
579
Andre Przywara161812c2023-06-07 01:07:43 +0100580 if (config->bus_full_width) {
Jernej Skrabec5a088482023-04-10 10:21:11 +0200581 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100582 if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
583 result = false;
584 }
585
586 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
587 }
588
589 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc);
590
591 return result;
592}
593
Andre Przywaraa21a22c2023-06-07 01:07:42 +0100594static void mctl_phy_bit_delay_compensation(const struct dram_para *para)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100595{
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200596 u32 *ptr, val;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100597 int i;
598
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200599 if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
600 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
601 setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
602 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100603
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200604 if (para->tpr10 & BIT(30))
605 val = para->tpr11 & 0x3f;
606 else
607 val = (para->tpr11 & 0xf) << 1;
608
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200609 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484);
610 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200611 writel_relaxed(val, ptr);
612 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200613 ptr += 2;
614 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200615
616 if (para->tpr10 & BIT(30))
617 val = (para->odt_en >> 15) & 0x1e;
618 else
619 val = (para->tpr11 >> 15) & 0x1e;
620
621 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4d0);
622 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x590);
623 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4cc);
624 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x58c);
625
626 if (para->tpr10 & BIT(30))
627 val = (para->tpr11 >> 8) & 0x3f;
628 else
629 val = (para->tpr11 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100630
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200631 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
632 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200633 writel_relaxed(val, ptr);
634 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200635 ptr += 2;
636 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200637
638 if (para->tpr10 & BIT(30))
639 val = (para->odt_en >> 19) & 0x1e;
640 else
641 val = (para->tpr11 >> 19) & 0x1e;
642
643 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x524);
644 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e4);
645 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x520);
646 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e0);
647
648 if (para->tpr10 & BIT(30))
649 val = (para->tpr11 >> 16) & 0x3f;
650 else
651 val = (para->tpr11 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100652
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200653 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604);
654 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200655 writel_relaxed(val, ptr);
656 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200657 ptr += 2;
658 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200659
660 if (para->tpr10 & BIT(30))
661 val = (para->odt_en >> 23) & 0x1e;
662 else
663 val = (para->tpr11 >> 23) & 0x1e;
664
665 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x650);
666 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x710);
667 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x64c);
668 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x70c);
669
670 if (para->tpr10 & BIT(30))
671 val = (para->tpr11 >> 24) & 0x3f;
672 else
673 val = (para->tpr11 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100674
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200675 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658);
676 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200677 writel_relaxed(val, ptr);
678 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200679 ptr += 2;
680 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200681
682 if (para->tpr10 & BIT(30))
683 val = (para->odt_en >> 27) & 0x1e;
684 else
685 val = (para->tpr11 >> 27) & 0x1e;
686
687 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a4);
688 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x764);
689 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a0);
690 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x760);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100691
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200692 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100693
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200694 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
695 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100696
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200697 if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
698 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
699 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100700
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200701 if (para->tpr10 & BIT(30))
702 val = para->tpr12 & 0x3f;
703 else
704 val = (para->tpr12 & 0xf) << 1;
705
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200706 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480);
707 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200708 writel_relaxed(val, ptr);
709 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200710 ptr += 2;
711 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200712
713 if (para->tpr10 & BIT(30))
714 val = (para->odt_en << 1) & 0x1e;
715 else
716 val = (para->tpr12 >> 15) & 0x1e;
717
718 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x528);
719 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5e8);
720 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x4c8);
721 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x588);
722
723 if (para->tpr10 & BIT(30))
724 val = (para->tpr12 >> 8) & 0x3f;
725 else
726 val = (para->tpr12 >> 3) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100727
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200728 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
729 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200730 writel_relaxed(val, ptr);
731 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200732 ptr += 2;
733 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200734
735 if (para->tpr10 & BIT(30))
736 val = (para->odt_en >> 3) & 0x1e;
737 else
738 val = (para->tpr12 >> 19) & 0x1e;
739
740 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x52c);
741 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5ec);
742 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x51c);
743 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x5dc);
744
745 if (para->tpr10 & BIT(30))
746 val = (para->tpr12 >> 16) & 0x3f;
747 else
748 val = (para->tpr12 >> 7) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100749
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200750 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600);
751 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200752 writel_relaxed(val, ptr);
753 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200754 ptr += 2;
755 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200756
757 if (para->tpr10 & BIT(30))
758 val = (para->odt_en >> 7) & 0x1e;
759 else
760 val = (para->tpr12 >> 23) & 0x1e;
761
762 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6a8);
763 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x768);
764 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x648);
765 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x708);
766
767 if (para->tpr10 & BIT(30))
768 val = (para->tpr12 >> 24) & 0x3f;
769 else
770 val = (para->tpr12 >> 11) & 0x1e;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100771
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200772 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x654);
773 for (i = 0; i < 9; i++) {
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200774 writel_relaxed(val, ptr);
775 writel_relaxed(val, ptr + 0x30);
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200776 ptr += 2;
777 }
Jernej Skrabec63ab9552023-04-10 10:21:16 +0200778
779 if (para->tpr10 & BIT(30))
780 val = (para->odt_en >> 11) & 0x1e;
781 else
782 val = (para->tpr12 >> 27) & 0x1e;
783
784 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x6ac);
785 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x76c);
786 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x69c);
787 writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x75c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100788
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200789 dmb();
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100790
Jernej Skrabec6a6fe862023-04-10 10:21:13 +0200791 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
792 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100793}
794
Andre Przywara161812c2023-06-07 01:07:43 +0100795static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para,
796 const struct dram_config *config)
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200797{
798 u32 val, *ptr;
799 int i;
800
801 if (para->tpr0 & BIT(30))
802 val = (para->tpr0 >> 7) & 0x3e;
803 else
804 val = (para->tpr10 >> 3) & 0x1e;
805
806 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
807 for (i = 0; i < 32; i++)
808 writel(val, &ptr[i]);
809
810 val = (para->tpr10 << 1) & 0x1e;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200811 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d8);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200812 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7dc);
813 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e0);
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200814 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f4);
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200815
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100816 if (para->type == SUNXI_DRAM_TYPE_DDR3) {
817 val = (para->tpr10 >> 7) & 0x1e;
818 if (para->tpr2 & 1) {
819 writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
820 if (config->ranks == 2) {
821 val = (para->tpr10 >> 11) & 0x1e;
822 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
823 }
824 if (para->tpr0 & BIT(31)) {
825 val = (para->tpr0 << 1) & 0x3e;
826 writel(val, SUNXI_DRAM_PHY0_BASE + 0x790);
827 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
828 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7cc);
829 }
830 } else {
831 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
832 if (config->ranks == 2) {
833 val = (para->tpr10 >> 11) & 0x1e;
834 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
835 }
836 if (para->tpr0 & BIT(31)) {
837 val = (para->tpr0 << 1) & 0x3e;
838 writel(val, SUNXI_DRAM_PHY0_BASE + 0x78c);
839 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a4);
840 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7b8);
841 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200842 }
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100843 } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
844 val = (para->tpr10 >> 7) & 0x1e;
845 if (para->tpr2 & 1) {
846 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7a0);
847 if (config->ranks == 2) {
848 val = (para->tpr10 >> 11) & 0x1e;
849 writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
850 }
851 } else {
852 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e8);
853 if (config->ranks == 2) {
854 val = (para->tpr10 >> 11) & 0x1e;
855 writel(val, SUNXI_DRAM_PHY0_BASE + 0x7f8);
856 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200857 }
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200858 }
859}
860
Andre Przywara161812c2023-06-07 01:07:43 +0100861static bool mctl_phy_init(const struct dram_para *para,
862 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100863{
864 struct sunxi_mctl_com_reg * const mctl_com =
865 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
866 struct sunxi_mctl_ctl_reg * const mctl_ctl =
867 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200868 u32 val, val2, *ptr, mr0, mr2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100869 int i;
870
Andre Przywara161812c2023-06-07 01:07:43 +0100871 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100872 val = 0xf;
873 else
874 val = 3;
875 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
876
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200877 if (para->tpr2 & 0x100) {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100878 if (para->type == SUNXI_DRAM_TYPE_DDR3) {
879 val = 9;
880 val2 = 7;
881 } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
882 // untested setup: use some values for now
883 val = 14;
884 val2 = 8;
885 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200886 } else {
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100887 if (para->type == SUNXI_DRAM_TYPE_DDR3) {
888 val = 13;
889 val2 = 9;
890 } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
891 val = 14;
892 val2 = 8;
893 }
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200894 }
895
896 writel(val, SUNXI_DRAM_PHY0_BASE + 0x14);
897 writel(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
898 writel(val, SUNXI_DRAM_PHY0_BASE + 0x368);
899 writel(val, SUNXI_DRAM_PHY0_BASE + 0x374);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100900
901 writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
902 writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
903 writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
904 writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
905
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200906 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
907 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
908 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
909 writel(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100910
Jernej Skrabec5a088482023-04-10 10:21:11 +0200911 ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100912 for (i = 0; i < ARRAY_SIZE(phy_init); i++)
913 writel(phy_init[i], &ptr[i]);
914
Jernej Skrabec9ec04b02023-04-10 10:21:17 +0200915 if (para->tpr10 & TPR10_CA_BIT_DELAY)
Andre Przywara161812c2023-06-07 01:07:43 +0100916 mctl_phy_ca_bit_delay_compensation(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100917
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100918 if (para->type == SUNXI_DRAM_TYPE_DDR3)
919 val = 0x80;
920 else if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
921 val = 0xc0;
922 writel(val, SUNXI_DRAM_PHY0_BASE + 0x3dc);
923 writel(val, SUNXI_DRAM_PHY0_BASE + 0x45c);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100924
Jernej Skrabec64712da2023-04-10 10:21:14 +0200925 mctl_phy_configure_odt(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100926
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100927 if (para->type == SUNXI_DRAM_TYPE_DDR3)
928 val = 0x0a;
929 else if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
930 val = 0x0b;
931 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x7, val);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100932
933 if (para->clk <= 672)
934 writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
935 if (para->clk > 500) {
936 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
937 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
938 } else {
939 setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
940 clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
941 }
942
943 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
944
Jernej Skrabec5a088482023-04-10 10:21:11 +0200945 mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100946
947 writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
948 clrbits_le32(&mctl_com->unk_0x500, 0x200);
949
950 writel(0, &mctl_ctl->swctl);
951 setbits_le32(&mctl_ctl->dfimisc, 1);
952
953 /* start DFI init */
954 setbits_le32(&mctl_ctl->dfimisc, 0x20);
955 writel(1, &mctl_ctl->swctl);
956 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
957 /* poll DFI init complete */
958 mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
959 writel(0, &mctl_ctl->swctl);
960 clrbits_le32(&mctl_ctl->dfimisc, 0x20);
961
962 clrbits_le32(&mctl_ctl->pwrctl, 0x20);
963 writel(1, &mctl_ctl->swctl);
964 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
965 mctl_await_completion(&mctl_ctl->statr, 3, 1);
966
967 writel(0, &mctl_ctl->swctl);
968 clrbits_le32(&mctl_ctl->dfimisc, 1);
969
970 writel(1, &mctl_ctl->swctl);
971 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
972
Jernej Skrabecac8154d2023-04-10 10:21:19 +0200973 if (para->tpr2 & 0x100) {
974 mr0 = 0x1b50;
975 mr2 = 0x10;
976 } else {
977 mr0 = 0x1f14;
978 mr2 = 0x20;
979 }
980
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100981 if (para->type == SUNXI_DRAM_TYPE_DDR3) {
982 writel(mr0, &mctl_ctl->mrctrl1);
983 writel(0x80000030, &mctl_ctl->mrctrl0);
984 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100985
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100986 writel(4, &mctl_ctl->mrctrl1);
987 writel(0x80001030, &mctl_ctl->mrctrl0);
988 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100989
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100990 writel(mr2, &mctl_ctl->mrctrl1);
991 writel(0x80002030, &mctl_ctl->mrctrl0);
992 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +0100993
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +0100994 writel(0, &mctl_ctl->mrctrl1);
995 writel(0x80003030, &mctl_ctl->mrctrl0);
996 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
997 } else if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
998 writel(mr0, &mctl_ctl->mrctrl1);
999 writel(0x800000f0, &mctl_ctl->mrctrl0);
1000 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1001
1002 writel(4, &mctl_ctl->mrctrl1);
1003 writel(0x800000f0, &mctl_ctl->mrctrl0);
1004 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1005
1006 writel(mr2, &mctl_ctl->mrctrl1);
1007 writel(0x800000f0, &mctl_ctl->mrctrl0);
1008 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1009
1010 writel(0x301, &mctl_ctl->mrctrl1);
1011 writel(0x800000f0, &mctl_ctl->mrctrl0);
1012 mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
1013 }
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001014
1015 writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
1016
1017 writel(0, &mctl_ctl->swctl);
1018 clrbits_le32(&mctl_ctl->rfshctl3, 1);
1019 writel(1, &mctl_ctl->swctl);
1020
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001021 if (para->tpr10 & TPR10_WRITE_LEVELING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001022 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001023 if (mctl_phy_write_leveling(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001024 break;
1025 if (i == 5) {
1026 debug("write leveling failed!\n");
1027 return false;
1028 }
1029 }
1030
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001031 if (para->tpr10 & TPR10_READ_CALIBRATION) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001032 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001033 if (mctl_phy_read_calibration(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001034 break;
1035 if (i == 5) {
1036 debug("read calibration failed!\n");
1037 return false;
1038 }
1039 }
1040
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001041 if (para->tpr10 & TPR10_READ_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001042 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001043 if (mctl_phy_read_training(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001044 break;
1045 if (i == 5) {
1046 debug("read training failed!\n");
1047 return false;
1048 }
1049 }
1050
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001051 if (para->tpr10 & TPR10_WRITE_TRAINING) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001052 for (i = 0; i < 5; i++)
Andre Przywara161812c2023-06-07 01:07:43 +01001053 if (mctl_phy_write_training(config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001054 break;
1055 if (i == 5) {
1056 debug("write training failed!\n");
1057 return false;
1058 }
1059 }
1060
Jernej Skrabec6a6fe862023-04-10 10:21:13 +02001061 mctl_phy_bit_delay_compensation(para);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001062
1063 clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
1064
1065 return true;
1066}
1067
Andre Przywara161812c2023-06-07 01:07:43 +01001068static bool mctl_ctrl_init(const struct dram_para *para,
1069 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001070{
1071 struct sunxi_mctl_com_reg * const mctl_com =
1072 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
1073 struct sunxi_mctl_ctl_reg * const mctl_ctl =
1074 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
1075 u32 reg_val;
1076
1077 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
1078 writel(0x8000, &mctl_ctl->clken);
1079
1080 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1081
1082 clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
1083
1084 writel(0, &mctl_ctl->hwlpctl);
1085
1086 setbits_le32(&mctl_com->unk_0x008, 0xff00);
1087
Andre Przywara161812c2023-06-07 01:07:43 +01001088 reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(config->ranks);
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001089 if (para->type == SUNXI_DRAM_TYPE_DDR3)
1090 reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
1091 else if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
1092 reg_val |= MSTR_DEVICETYPE_LPDDR3;
Andre Przywara161812c2023-06-07 01:07:43 +01001093 if (config->bus_full_width)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001094 reg_val |= MSTR_BUSWIDTH_FULL;
1095 else
1096 reg_val |= MSTR_BUSWIDTH_HALF;
1097 writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
1098
Andre Przywara161812c2023-06-07 01:07:43 +01001099 if (config->ranks == 2)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001100 writel(0x0303, &mctl_ctl->odtmap);
1101 else
1102 writel(0x0201, &mctl_ctl->odtmap);
1103
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001104 if (para->type == SUNXI_DRAM_TYPE_DDR3)
1105 reg_val = 0x06000400;
1106 else if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
1107 reg_val = 0x09020400;
1108 writel(reg_val, &mctl_ctl->odtcfg);
1109 writel(reg_val, &mctl_ctl->unk_0x2240);
1110 writel(reg_val, &mctl_ctl->unk_0x3240);
1111 writel(reg_val, &mctl_ctl->unk_0x4240);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001112
Jernej Skrabec472d4042023-04-10 10:21:10 +02001113 writel(BIT(31), &mctl_com->cr);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001114
Andre Przywara161812c2023-06-07 01:07:43 +01001115 mctl_set_addrmap(config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001116
1117 mctl_set_timing_params(para);
1118
1119 writel(0, &mctl_ctl->pwrctl);
1120
1121 setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
1122 setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
1123 setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
1124 setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
1125 setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
1126
1127 setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1128 clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
1129
1130 writel(0, &mctl_com->maer0);
1131 writel(0, &mctl_com->maer1);
1132 writel(0, &mctl_com->maer2);
1133
1134 writel(0x20, &mctl_ctl->pwrctl);
1135 setbits_le32(&mctl_ctl->clken, BIT(8));
1136
1137 clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
1138 /* this write seems to enable PHY MMIO region */
1139 setbits_le32(&mctl_com->unk_0x500, BIT(24));
1140
Andre Przywara161812c2023-06-07 01:07:43 +01001141 if (!mctl_phy_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001142 return false;
1143
1144 writel(0, &mctl_ctl->swctl);
1145 clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
1146
1147 setbits_le32(&mctl_com->unk_0x014, BIT(31));
1148 writel(0xffffffff, &mctl_com->maer0);
1149 writel(0x7ff, &mctl_com->maer1);
1150 writel(0xffff, &mctl_com->maer2);
1151
1152 writel(1, &mctl_ctl->swctl);
1153 mctl_await_completion(&mctl_ctl->swstat, 1, 1);
1154
1155 return true;
1156}
1157
Andre Przywara161812c2023-06-07 01:07:43 +01001158static bool mctl_core_init(const struct dram_para *para,
1159 const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001160{
Andre Przywaraa21a22c2023-06-07 01:07:42 +01001161 mctl_sys_init(para->clk);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001162
Andre Przywara161812c2023-06-07 01:07:43 +01001163 return mctl_ctrl_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001164}
1165
Andre Przywara161812c2023-06-07 01:07:43 +01001166static void mctl_auto_detect_rank_width(const struct dram_para *para,
1167 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001168{
1169 /* this is minimum size that it's supported */
Andre Przywara161812c2023-06-07 01:07:43 +01001170 config->cols = 8;
1171 config->rows = 13;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001172
1173 /*
1174 * Strategy here is to test most demanding combination first and least
1175 * demanding last, otherwise HW might not be fully utilized. For
1176 * example, half bus width and rank = 1 combination would also work
1177 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
1178 * visible.
1179 */
1180
1181 debug("testing 32-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001182 config->bus_full_width = 1;
1183 config->ranks = 2;
1184 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001185 return;
1186
1187 debug("testing 32-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001188 config->bus_full_width = 1;
1189 config->ranks = 1;
1190 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001191 return;
1192
1193 debug("testing 16-bit width, rank = 2\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001194 config->bus_full_width = 0;
1195 config->ranks = 2;
1196 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001197 return;
1198
1199 debug("testing 16-bit width, rank = 1\n");
Andre Przywara161812c2023-06-07 01:07:43 +01001200 config->bus_full_width = 0;
1201 config->ranks = 1;
1202 if (mctl_core_init(para, config))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001203 return;
1204
1205 panic("This DRAM setup is currently not supported.\n");
1206}
1207
Andre Przywara161812c2023-06-07 01:07:43 +01001208static void mctl_auto_detect_dram_size(const struct dram_para *para,
1209 struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001210{
1211 /* detect row address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001212 config->cols = 8;
1213 config->rows = 18;
1214 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001215
Andre Przywara161812c2023-06-07 01:07:43 +01001216 for (config->rows = 13; config->rows < 18; config->rows++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001217 /* 8 banks, 8 bit per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001218 if (mctl_mem_matches((1 << (config->rows + config->cols +
1219 4 + config->bus_full_width))))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001220 break;
1221 }
1222
1223 /* detect column address bits */
Andre Przywara161812c2023-06-07 01:07:43 +01001224 config->cols = 11;
1225 mctl_core_init(para, config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001226
Andre Przywara161812c2023-06-07 01:07:43 +01001227 for (config->cols = 8; config->cols < 11; config->cols++) {
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001228 /* 8 bits per byte and 16/32 bit width */
Andre Przywara161812c2023-06-07 01:07:43 +01001229 if (mctl_mem_matches(1 << (config->cols + 1 +
1230 config->bus_full_width)))
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001231 break;
1232 }
1233}
1234
Andre Przywara161812c2023-06-07 01:07:43 +01001235static unsigned long mctl_calc_size(const struct dram_config *config)
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001236{
Andre Przywara161812c2023-06-07 01:07:43 +01001237 u8 width = config->bus_full_width ? 4 : 2;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001238
1239 /* 8 banks */
Andre Przywara161812c2023-06-07 01:07:43 +01001240 return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001241}
1242
Andre Przywara161812c2023-06-07 01:07:43 +01001243static const struct dram_para para = {
1244 .clk = CONFIG_DRAM_CLK,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001245#ifdef CONFIG_SUNXI_DRAM_H616_DDR3_1333
Andre Przywara161812c2023-06-07 01:07:43 +01001246 .type = SUNXI_DRAM_TYPE_DDR3,
Mikhail Kalashnikovcfce8e42023-06-07 01:07:45 +01001247#elif defined(CONFIG_SUNXI_DRAM_H616_LPDDR3)
1248 .type = SUNXI_DRAM_TYPE_LPDDR3,
1249#endif
Andre Przywara161812c2023-06-07 01:07:43 +01001250 .dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
1251 .dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
1252 .ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
1253 .odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
1254 .tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
1255 .tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
1256 .tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
1257 .tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
1258 .tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
1259};
1260
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001261unsigned long sunxi_dram_init(void)
1262{
Jernej Skrabece04cd492022-01-30 15:27:13 +01001263 struct sunxi_prcm_reg *const prcm =
1264 (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
Andre Przywara161812c2023-06-07 01:07:43 +01001265 struct dram_config config;
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001266 unsigned long size;
1267
Jernej Skrabece04cd492022-01-30 15:27:13 +01001268 setbits_le32(&prcm->res_cal_ctrl, BIT(8));
1269 clrbits_le32(&prcm->ohms240, 0x3f);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001270
Andre Przywara161812c2023-06-07 01:07:43 +01001271 mctl_auto_detect_rank_width(&para, &config);
1272 mctl_auto_detect_dram_size(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001273
Andre Przywara161812c2023-06-07 01:07:43 +01001274 mctl_core_init(&para, &config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001275
Andre Przywara161812c2023-06-07 01:07:43 +01001276 size = mctl_calc_size(&config);
Jernej Skrabece4aa24b2021-01-11 21:11:43 +01001277
1278 mctl_set_master_priority();
1279
1280 return size;
1281};