blob: 9f7cc7fd4ccdcec499519ed0d89dd0f8687bc7cc [file] [log] [blame]
Jens Kuske53f018e2015-11-17 15:12:59 +01001/*
2 * sun8i H3 platform dram controller init
3 *
4 * (C) Copyright 2007-2015 Allwinner Technology Co.
5 * Jerry Wang <wangflord@allwinnertech.com>
6 * (C) Copyright 2015 Vishnu Patekar <vishnupatekar0510@gmail.com>
7 * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
8 * (C) Copyright 2015 Jens Kuske <jenskuske@gmail.com>
9 *
10 * SPDX-License-Identifier: GPL-2.0+
11 */
12#include <common.h>
13#include <asm/io.h>
14#include <asm/arch/clock.h>
15#include <asm/arch/dram.h>
Jens Kuskef6138172017-01-02 11:48:42 +000016#include <asm/arch/cpu.h>
Jens Kuske53f018e2015-11-17 15:12:59 +010017#include <linux/kconfig.h>
18
Jens Kuske8bbadc82017-01-02 11:48:40 +000019/*
20 * The delay parameters below allow to allegedly specify delay times of some
21 * unknown unit for each individual bit trace in each of the four data bytes
22 * the 32-bit wide access consists of. Also three control signals can be
23 * adjusted individually.
24 */
25#define BITS_PER_BYTE 8
26#define NR_OF_BYTE_LANES (32 / BITS_PER_BYTE)
27/* The eight data lines (DQn) plus DM, DQS and DQSN */
28#define LINES_PER_BYTE_LANE (BITS_PER_BYTE + 3)
Jens Kuske53f018e2015-11-17 15:12:59 +010029struct dram_para {
Jens Kuske53f018e2015-11-17 15:12:59 +010030 u16 page_size;
31 u8 bus_width;
32 u8 dual_rank;
33 u8 row_bits;
Jens Kuske8bbadc82017-01-02 11:48:40 +000034 const u8 dx_read_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE];
35 const u8 dx_write_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE];
36 const u8 ac_delays[31];
Jens Kuske53f018e2015-11-17 15:12:59 +010037};
38
39static inline int ns_to_t(int nanoseconds)
40{
41 const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
42
43 return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
44}
45
Jens Kuske53f018e2015-11-17 15:12:59 +010046static void mctl_phy_init(u32 val)
47{
48 struct sunxi_mctl_ctl_reg * const mctl_ctl =
49 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
50
51 writel(val | PIR_INIT, &mctl_ctl->pir);
52 mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1);
53}
54
Jens Kuske8bbadc82017-01-02 11:48:40 +000055static void mctl_set_bit_delays(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +010056{
57 struct sunxi_mctl_ctl_reg * const mctl_ctl =
58 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
59 int i, j;
Jens Kuske53f018e2015-11-17 15:12:59 +010060
61 clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
62
Jens Kuske8bbadc82017-01-02 11:48:40 +000063 for (i = 0; i < NR_OF_BYTE_LANES; i++)
64 for (j = 0; j < LINES_PER_BYTE_LANE; j++)
65 writel(DXBDLR_WRITE_DELAY(para->dx_write_delays[i][j]) |
66 DXBDLR_READ_DELAY(para->dx_read_delays[i][j]),
67 &mctl_ctl->dx[i].bdlr[j]);
Jens Kuske53f018e2015-11-17 15:12:59 +010068
Jens Kuske8bbadc82017-01-02 11:48:40 +000069 for (i = 0; i < 31; i++)
70 writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
71 &mctl_ctl->acbdlr[i]);
Jens Kuske53f018e2015-11-17 15:12:59 +010072
73 setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
Jens Kuske53f018e2015-11-17 15:12:59 +010074}
75
Philipp Tomsich3c31ba92017-01-02 11:48:38 +000076enum {
77 MBUS_PORT_CPU = 0,
78 MBUS_PORT_GPU = 1,
79 MBUS_PORT_UNUSED = 2,
80 MBUS_PORT_DMA = 3,
81 MBUS_PORT_VE = 4,
82 MBUS_PORT_CSI = 5,
83 MBUS_PORT_NAND = 6,
84 MBUS_PORT_SS = 7,
85 MBUS_PORT_TS = 8,
86 MBUS_PORT_DI = 9,
87 MBUS_PORT_DE = 10,
88 MBUS_PORT_DE_CFD = 11,
89};
90
91enum {
92 MBUS_QOS_LOWEST = 0,
93 MBUS_QOS_LOW,
94 MBUS_QOS_HIGH,
95 MBUS_QOS_HIGHEST
96};
97
98inline void mbus_configure_port(u8 port,
99 bool bwlimit,
100 bool priority,
101 u8 qos, /* MBUS_QOS_LOWEST .. MBUS_QOS_HIGEST */
102 u8 waittime, /* 0 .. 0xf */
103 u8 acs, /* 0 .. 0xff */
104 u16 bwl0, /* 0 .. 0xffff, bandwidth limit in MB/s */
105 u16 bwl1,
106 u16 bwl2)
107{
108 struct sunxi_mctl_com_reg * const mctl_com =
109 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
110
111 const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
112 | (priority ? (1 << 1) : 0)
113 | ((qos & 0x3) << 2)
114 | ((waittime & 0xf) << 4)
115 | ((acs & 0xff) << 8)
116 | (bwl0 << 16) );
117 const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
118
119 debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
120 writel(cfg0, &mctl_com->mcr[port][0]);
121 writel(cfg1, &mctl_com->mcr[port][1]);
122}
123
124#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2) \
125 mbus_configure_port(MBUS_PORT_ ## port, bwlimit, false, \
126 MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
127
Jens Kuskef6138172017-01-02 11:48:42 +0000128static void mctl_set_master_priority_h3(void)
Jens Kuske53f018e2015-11-17 15:12:59 +0100129{
130 struct sunxi_mctl_com_reg * const mctl_com =
131 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
132
133 /* enable bandwidth limit windows and set windows size 1us */
Jens Kuskef6138172017-01-02 11:48:42 +0000134 writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100135
136 /* set cpu high priority */
137 writel(0x00000001, &mctl_com->mapr);
138
Philipp Tomsich3c31ba92017-01-02 11:48:38 +0000139 MBUS_CONF( CPU, true, HIGHEST, 0, 512, 256, 128);
140 MBUS_CONF( GPU, true, HIGH, 0, 1536, 1024, 256);
141 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
142 MBUS_CONF( DMA, true, HIGHEST, 0, 256, 128, 32);
143 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
144 MBUS_CONF( CSI, true, HIGHEST, 0, 256, 128, 32);
145 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
146 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
147 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
148 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
149 MBUS_CONF( DE, true, HIGHEST, 3, 8192, 6120, 1024);
150 MBUS_CONF(DE_CFD, true, HIGH, 0, 1024, 288, 64);
Jens Kuske53f018e2015-11-17 15:12:59 +0100151}
152
Jens Kuskef6138172017-01-02 11:48:42 +0000153static void mctl_set_master_priority_a64(void)
154{
155 struct sunxi_mctl_com_reg * const mctl_com =
156 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
157
158 /* enable bandwidth limit windows and set windows size 1us */
159 writel(399, &mctl_com->tmr);
160 writel((1 << 16), &mctl_com->bwcr);
161
162 /* Port 2 is reserved per Allwinner's linux-3.10 source, yet they
163 * initialise it */
164 MBUS_CONF( CPU, true, HIGHEST, 0, 160, 100, 80);
165 MBUS_CONF( GPU, false, HIGH, 0, 1536, 1400, 256);
166 MBUS_CONF(UNUSED, true, HIGHEST, 0, 512, 256, 96);
167 MBUS_CONF( DMA, true, HIGH, 0, 256, 80, 100);
168 MBUS_CONF( VE, true, HIGH, 0, 1792, 1600, 256);
169 MBUS_CONF( CSI, true, HIGH, 0, 256, 128, 0);
170 MBUS_CONF( NAND, true, HIGH, 0, 256, 128, 64);
171 MBUS_CONF( SS, true, HIGHEST, 0, 256, 128, 64);
172 MBUS_CONF( TS, true, HIGHEST, 0, 256, 128, 64);
173 MBUS_CONF( DI, true, HIGH, 0, 1024, 256, 64);
174 MBUS_CONF( DE, true, HIGH, 2, 8192, 6144, 2048);
175 MBUS_CONF(DE_CFD, true, HIGH, 0, 1280, 144, 64);
176
177 writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
178}
179
180static void mctl_set_master_priority(uint16_t socid)
181{
182 switch (socid) {
183 case SOCID_H3:
184 mctl_set_master_priority_h3();
185 return;
186 case SOCID_A64:
187 mctl_set_master_priority_a64();
188 return;
189 }
190}
191
192static void mctl_set_timing_params(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100193{
194 struct sunxi_mctl_ctl_reg * const mctl_ctl =
195 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
196
197 u8 tccd = 2;
198 u8 tfaw = ns_to_t(50);
199 u8 trrd = max(ns_to_t(10), 4);
200 u8 trcd = ns_to_t(15);
201 u8 trc = ns_to_t(53);
202 u8 txp = max(ns_to_t(8), 3);
203 u8 twtr = max(ns_to_t(8), 4);
204 u8 trtp = max(ns_to_t(8), 4);
205 u8 twr = max(ns_to_t(15), 3);
206 u8 trp = ns_to_t(15);
207 u8 tras = ns_to_t(38);
208 u16 trefi = ns_to_t(7800) / 32;
209 u16 trfc = ns_to_t(350);
210
211 u8 tmrw = 0;
212 u8 tmrd = 4;
213 u8 tmod = 12;
214 u8 tcke = 3;
215 u8 tcksrx = 5;
216 u8 tcksre = 5;
217 u8 tckesr = 4;
218 u8 trasmax = 24;
219
220 u8 tcl = 6; /* CL 12 */
221 u8 tcwl = 4; /* CWL 8 */
222 u8 t_rdata_en = 4;
223 u8 wr_latency = 2;
224
225 u32 tdinit0 = (500 * CONFIG_DRAM_CLK) + 1; /* 500us */
226 u32 tdinit1 = (360 * CONFIG_DRAM_CLK) / 1000 + 1; /* 360ns */
227 u32 tdinit2 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */
228 u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */
229
230 u8 twtp = tcwl + 2 + twr; /* WL + BL / 2 + tWR */
231 u8 twr2rd = tcwl + 2 + twtr; /* WL + BL / 2 + tWTR */
232 u8 trd2wr = tcl + 2 + 1 - tcwl; /* RL + BL / 2 + 2 - WL */
233
234 /* set mode register */
235 writel(0x1c70, &mctl_ctl->mr[0]); /* CL=11, WR=12 */
236 writel(0x40, &mctl_ctl->mr[1]);
237 writel(0x18, &mctl_ctl->mr[2]); /* CWL=8 */
238 writel(0x0, &mctl_ctl->mr[3]);
239
240 /* set DRAM timing */
241 writel(DRAMTMG0_TWTP(twtp) | DRAMTMG0_TFAW(tfaw) |
242 DRAMTMG0_TRAS_MAX(trasmax) | DRAMTMG0_TRAS(tras),
243 &mctl_ctl->dramtmg[0]);
244 writel(DRAMTMG1_TXP(txp) | DRAMTMG1_TRTP(trtp) | DRAMTMG1_TRC(trc),
245 &mctl_ctl->dramtmg[1]);
246 writel(DRAMTMG2_TCWL(tcwl) | DRAMTMG2_TCL(tcl) |
247 DRAMTMG2_TRD2WR(trd2wr) | DRAMTMG2_TWR2RD(twr2rd),
248 &mctl_ctl->dramtmg[2]);
249 writel(DRAMTMG3_TMRW(tmrw) | DRAMTMG3_TMRD(tmrd) | DRAMTMG3_TMOD(tmod),
250 &mctl_ctl->dramtmg[3]);
251 writel(DRAMTMG4_TRCD(trcd) | DRAMTMG4_TCCD(tccd) | DRAMTMG4_TRRD(trrd) |
252 DRAMTMG4_TRP(trp), &mctl_ctl->dramtmg[4]);
253 writel(DRAMTMG5_TCKSRX(tcksrx) | DRAMTMG5_TCKSRE(tcksre) |
254 DRAMTMG5_TCKESR(tckesr) | DRAMTMG5_TCKE(tcke),
255 &mctl_ctl->dramtmg[5]);
256
257 /* set two rank timing */
258 clrsetbits_le32(&mctl_ctl->dramtmg[8], (0xff << 8) | (0xff << 0),
259 (0x66 << 8) | (0x10 << 0));
260
261 /* set PHY interface timing, write latency and read latency configure */
262 writel((0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) |
263 (wr_latency << 0), &mctl_ctl->pitmg[0]);
264
265 /* set PHY timing, PTR0-2 use default */
266 writel(PTR3_TDINIT0(tdinit0) | PTR3_TDINIT1(tdinit1), &mctl_ctl->ptr[3]);
267 writel(PTR4_TDINIT2(tdinit2) | PTR4_TDINIT3(tdinit3), &mctl_ctl->ptr[4]);
268
269 /* set refresh timing */
270 writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg);
271}
272
Jens Kuskef6138172017-01-02 11:48:42 +0000273static u32 bin_to_mgray(int val)
274{
275 static const u8 lookup_table[32] = {
276 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
277 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
278 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
279 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
280 };
281
282 return lookup_table[clamp(val, 0, 31)];
283}
284
285static int mgray_to_bin(u32 val)
286{
287 static const u8 lookup_table[32] = {
288 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
289 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
290 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
291 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
292 };
293
294 return lookup_table[val & 0x1f];
295}
296
297static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100298{
299 struct sunxi_mctl_ctl_reg * const mctl_ctl =
300 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
301
Jens Kusked8b95932016-09-21 20:08:30 +0200302 if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
303 (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
304 u32 reg_val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100305
Jens Kusked8b95932016-09-21 20:08:30 +0200306 clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
307 CONFIG_DRAM_ZQ & 0xffff);
Jens Kuske53f018e2015-11-17 15:12:59 +0100308
309 writel(PIR_CLRSR, &mctl_ctl->pir);
310 mctl_phy_init(PIR_ZCAL);
311
Jens Kusked8b95932016-09-21 20:08:30 +0200312 reg_val = readl(&mctl_ctl->zqdr[0]);
313 reg_val &= (0x1f << 16) | (0x1f << 0);
314 reg_val |= reg_val << 8;
315 writel(reg_val, &mctl_ctl->zqdr[0]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100316
Jens Kusked8b95932016-09-21 20:08:30 +0200317 reg_val = readl(&mctl_ctl->zqdr[1]);
318 reg_val &= (0x1f << 16) | (0x1f << 0);
319 reg_val |= reg_val << 8;
320 writel(reg_val, &mctl_ctl->zqdr[1]);
321 writel(reg_val, &mctl_ctl->zqdr[2]);
322 } else {
323 int i;
324 u16 zq_val[6];
325 u8 val;
Jens Kuske53f018e2015-11-17 15:12:59 +0100326
Jens Kusked8b95932016-09-21 20:08:30 +0200327 writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
328
329 for (i = 0; i < 6; i++) {
330 u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
Jens Kuske53f018e2015-11-17 15:12:59 +0100331
Jens Kusked8b95932016-09-21 20:08:30 +0200332 writel((zq << 20) | (zq << 16) | (zq << 12) |
333 (zq << 8) | (zq << 4) | (zq << 0),
334 &mctl_ctl->zqcr);
335
336 writel(PIR_CLRSR, &mctl_ctl->pir);
337 mctl_phy_init(PIR_ZCAL);
338
339 zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
340 writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
341
342 writel(PIR_CLRSR, &mctl_ctl->pir);
343 mctl_phy_init(PIR_ZCAL);
344
345 val = readl(&mctl_ctl->zqdr[0]) >> 24;
346 zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
347 }
348
349 writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
350 writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
351 writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
352 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100353}
354
355static void mctl_set_cr(struct dram_para *para)
356{
357 struct sunxi_mctl_com_reg * const mctl_com =
358 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
359
360 writel(MCTL_CR_BL8 | MCTL_CR_2T | MCTL_CR_DDR3 | MCTL_CR_INTERLEAVED |
361 MCTL_CR_EIGHT_BANKS | MCTL_CR_BUS_WIDTH(para->bus_width) |
362 (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
363 MCTL_CR_PAGE_SIZE(para->page_size) |
364 MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr);
365}
366
Jens Kuskef6138172017-01-02 11:48:42 +0000367static void mctl_sys_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100368{
369 struct sunxi_ccm_reg * const ccm =
370 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
371 struct sunxi_mctl_ctl_reg * const mctl_ctl =
372 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
373
374 clrbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
375 clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
376 clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
377 clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
378 clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
Jens Kuskef6138172017-01-02 11:48:42 +0000379 if (socid == SOCID_A64)
380 clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
Jens Kuske53f018e2015-11-17 15:12:59 +0100381 udelay(10);
382
383 clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
384 udelay(1000);
385
Jens Kuskef6138172017-01-02 11:48:42 +0000386 if (socid == SOCID_A64) {
387 clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
388 clrsetbits_le32(&ccm->dram_clk_cfg,
389 CCM_DRAMCLK_CFG_DIV_MASK |
390 CCM_DRAMCLK_CFG_SRC_MASK,
391 CCM_DRAMCLK_CFG_DIV(1) |
392 CCM_DRAMCLK_CFG_SRC_PLL11 |
393 CCM_DRAMCLK_CFG_UPD);
394 } else if (socid == SOCID_H3) {
395 clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
396 clrsetbits_le32(&ccm->dram_clk_cfg,
397 CCM_DRAMCLK_CFG_DIV_MASK |
398 CCM_DRAMCLK_CFG_SRC_MASK,
399 CCM_DRAMCLK_CFG_DIV(1) |
400 CCM_DRAMCLK_CFG_SRC_PLL5 |
401 CCM_DRAMCLK_CFG_UPD);
402 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100403 mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
404
405 setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
406 setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
407 setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET);
408 setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE);
409
410 setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
411 udelay(10);
412
413 writel(0xc00e, &mctl_ctl->clken);
414 udelay(500);
415}
416
Andre Przywarac98f5cc2017-01-02 11:48:43 +0000417/* These are more guessed based on some Allwinner code. */
418#define DX_GCR_ODT_DYNAMIC (0x0 << 4)
419#define DX_GCR_ODT_ALWAYS_ON (0x1 << 4)
420#define DX_GCR_ODT_OFF (0x2 << 4)
421
Jens Kuskef6138172017-01-02 11:48:42 +0000422static int mctl_channel_init(uint16_t socid, struct dram_para *para)
Jens Kuske53f018e2015-11-17 15:12:59 +0100423{
424 struct sunxi_mctl_com_reg * const mctl_com =
425 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
426 struct sunxi_mctl_ctl_reg * const mctl_ctl =
427 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
428
429 unsigned int i;
430
431 mctl_set_cr(para);
Jens Kuskef6138172017-01-02 11:48:42 +0000432 mctl_set_timing_params(socid, para);
433 mctl_set_master_priority(socid);
Jens Kuske53f018e2015-11-17 15:12:59 +0100434
435 /* setting VTC, default disable all VT */
436 clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f);
437 clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26);
438
439 /* increase DFI_PHY_UPD clock */
440 writel(PROTECT_MAGIC, &mctl_com->protect);
441 udelay(100);
442 clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16);
443 writel(0x0, &mctl_com->protect);
444 udelay(100);
445
446 /* set dramc odt */
447 for (i = 0; i < 4; i++)
Jens Kuske3e797582017-01-02 11:48:39 +0000448 clrsetbits_le32(&mctl_ctl->dx[i].gcr, (0x3 << 4) |
Jens Kuske53f018e2015-11-17 15:12:59 +0100449 (0x1 << 1) | (0x3 << 2) | (0x3 << 12) |
450 (0x3 << 14),
Andre Przywarac98f5cc2017-01-02 11:48:43 +0000451 IS_ENABLED(CONFIG_DRAM_ODT_EN) ?
452 DX_GCR_ODT_DYNAMIC : DX_GCR_ODT_OFF);
Jens Kuske53f018e2015-11-17 15:12:59 +0100453
454 /* AC PDR should always ON */
455 setbits_le32(&mctl_ctl->aciocr, 0x1 << 1);
456
457 /* set DQS auto gating PD mode */
458 setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
459
Jens Kuskef6138172017-01-02 11:48:42 +0000460 if (socid == SOCID_H3) {
461 /* dx ddr_clk & hdr_clk dynamic mode */
462 clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
Jens Kuske53f018e2015-11-17 15:12:59 +0100463
Jens Kuskef6138172017-01-02 11:48:42 +0000464 /* dphy & aphy phase select 270 degree */
465 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
466 (0x1 << 10) | (0x2 << 8));
467 } else if (socid == SOCID_A64) {
468 /* dphy & aphy phase select ? */
469 clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
470 (0x0 << 10) | (0x3 << 8));
471 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100472
473 /* set half DQ */
474 if (para->bus_width != 32) {
Jens Kuske3e797582017-01-02 11:48:39 +0000475 writel(0x0, &mctl_ctl->dx[2].gcr);
476 writel(0x0, &mctl_ctl->dx[3].gcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100477 }
478
479 /* data training configuration */
480 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24,
481 (para->dual_rank ? 0x3 : 0x1) << 24);
482
Jens Kuske8bbadc82017-01-02 11:48:40 +0000483 mctl_set_bit_delays(para);
484 udelay(50);
Jens Kuske53f018e2015-11-17 15:12:59 +0100485
Jens Kuskef6138172017-01-02 11:48:42 +0000486 if (socid == SOCID_H3) {
487 mctl_h3_zq_calibration_quirk(para);
Jens Kuske53f018e2015-11-17 15:12:59 +0100488
Jens Kuskef6138172017-01-02 11:48:42 +0000489 mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
490 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
491 } else if (socid == SOCID_A64) {
492 clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
493
494 mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
495 PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
496 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100497
498 /* detect ranks and bus width */
499 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
500 /* only one rank */
Jens Kuske3e797582017-01-02 11:48:39 +0000501 if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2) ||
502 ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)) {
Jens Kuske53f018e2015-11-17 15:12:59 +0100503 clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24);
504 para->dual_rank = 0;
505 }
506
507 /* only half DQ width */
Jens Kuske3e797582017-01-02 11:48:39 +0000508 if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) ||
509 ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) {
510 writel(0x0, &mctl_ctl->dx[2].gcr);
511 writel(0x0, &mctl_ctl->dx[3].gcr);
Jens Kuske53f018e2015-11-17 15:12:59 +0100512 para->bus_width = 16;
513 }
514
515 mctl_set_cr(para);
516 udelay(20);
517
518 /* re-train */
519 mctl_phy_init(PIR_QSGATE);
520 if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
521 return 1;
522 }
523
524 /* check the dramc status */
525 mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
526
527 /* liuke added for refresh debug */
528 setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
529 udelay(10);
530 clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
531 udelay(10);
532
533 /* set PGCR3, CKE polarity */
Jens Kuskef6138172017-01-02 11:48:42 +0000534 if (socid == SOCID_H3)
535 writel(0x00aa0060, &mctl_ctl->pgcr[3]);
536 else if (socid == SOCID_A64)
537 writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
Jens Kuske53f018e2015-11-17 15:12:59 +0100538
539 /* power down zq calibration module for power save */
540 setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
541
542 /* enable master access */
543 writel(0xffffffff, &mctl_com->maer);
544
545 return 0;
546}
547
548static void mctl_auto_detect_dram_size(struct dram_para *para)
549{
550 /* detect row address bits */
551 para->page_size = 512;
552 para->row_bits = 16;
553 mctl_set_cr(para);
554
555 for (para->row_bits = 11; para->row_bits < 16; para->row_bits++)
556 if (mctl_mem_matches((1 << (para->row_bits + 3)) * para->page_size))
557 break;
558
559 /* detect page size */
560 para->page_size = 8192;
561 mctl_set_cr(para);
562
563 for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2)
564 if (mctl_mem_matches(para->page_size))
565 break;
566}
567
Jens Kuske8bbadc82017-01-02 11:48:40 +0000568/*
569 * The actual values used here are taken from Allwinner provided boot0
570 * binaries, though they are probably board specific, so would likely benefit
571 * from invidual tuning for each board. Apparently a lot of boards copy from
572 * some Allwinner reference design, so we go with those generic values for now
573 * in the hope that they are reasonable for most (all?) boards.
574 */
575#define SUN8I_H3_DX_READ_DELAYS \
576 {{ 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
577 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }, \
578 { 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0 }, \
579 { 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0 }}
580#define SUN8I_H3_DX_WRITE_DELAYS \
581 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
582 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
583 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10 }, \
584 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 }}
585#define SUN8I_H3_AC_DELAYS \
586 { 0, 0, 0, 0, 0, 0, 0, 0, \
587 0, 0, 0, 0, 0, 0, 0, 0, \
588 0, 0, 0, 0, 0, 0, 0, 0, \
589 0, 0, 0, 0, 0, 0, 0 }
590
Jens Kuskef6138172017-01-02 11:48:42 +0000591#define SUN50I_A64_DX_READ_DELAYS \
592 {{ 16, 16, 16, 16, 17, 16, 16, 17, 16, 1, 0 }, \
593 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }, \
594 { 16, 17, 17, 16, 16, 16, 16, 16, 16, 0, 0 }, \
595 { 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0 }}
596#define SUN50I_A64_DX_WRITE_DELAYS \
597 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15 }, \
598 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 10, 10 }, \
599 { 1, 0, 1, 1, 1, 1, 1, 1, 0, 11, 11 }, \
600 { 1, 0, 0, 1, 1, 1, 1, 1, 0, 12, 12 }}
601#define SUN50I_A64_AC_DELAYS \
602 { 5, 5, 13, 10, 2, 5, 3, 3, \
603 0, 3, 3, 3, 1, 0, 0, 0, \
604 3, 4, 0, 3, 4, 1, 4, 0, \
605 1, 1, 0, 1, 13, 5, 4 }
606
Jens Kuske53f018e2015-11-17 15:12:59 +0100607unsigned long sunxi_dram_init(void)
608{
609 struct sunxi_mctl_com_reg * const mctl_com =
610 (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
611 struct sunxi_mctl_ctl_reg * const mctl_ctl =
612 (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
613
614 struct dram_para para = {
Jens Kuske53f018e2015-11-17 15:12:59 +0100615 .dual_rank = 0,
616 .bus_width = 32,
617 .row_bits = 15,
618 .page_size = 4096,
Jens Kuskef6138172017-01-02 11:48:42 +0000619
620#if defined(CONFIG_MACH_SUN8I_H3)
Jens Kuske8bbadc82017-01-02 11:48:40 +0000621 .dx_read_delays = SUN8I_H3_DX_READ_DELAYS,
622 .dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS,
623 .ac_delays = SUN8I_H3_AC_DELAYS,
Jens Kuskef6138172017-01-02 11:48:42 +0000624#elif defined(CONFIG_MACH_SUN50I)
625 .dx_read_delays = SUN50I_A64_DX_READ_DELAYS,
626 .dx_write_delays = SUN50I_A64_DX_WRITE_DELAYS,
627 .ac_delays = SUN50I_A64_AC_DELAYS,
628#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100629 };
Jens Kuskef6138172017-01-02 11:48:42 +0000630/*
631 * Let the compiler optimize alternatives away by passing this value into
632 * the static functions. This saves us #ifdefs, but still keeps the binary
633 * small.
634 */
635#if defined(CONFIG_MACH_SUN8I_H3)
636 uint16_t socid = SOCID_H3;
637#elif defined(CONFIG_MACH_SUN50I)
638 uint16_t socid = SOCID_A64;
639#endif
Jens Kuske53f018e2015-11-17 15:12:59 +0100640
Jens Kuskef6138172017-01-02 11:48:42 +0000641 mctl_sys_init(socid, &para);
642 if (mctl_channel_init(socid, &para))
Jens Kuske53f018e2015-11-17 15:12:59 +0100643 return 0;
644
645 if (para.dual_rank)
646 writel(0x00000303, &mctl_ctl->odtmap);
647 else
648 writel(0x00000201, &mctl_ctl->odtmap);
649 udelay(1);
650
651 /* odt delay */
Jens Kuskef6138172017-01-02 11:48:42 +0000652 if (socid == SOCID_H3)
653 writel(0x0c000400, &mctl_ctl->odtcfg);
654
655 if (socid == SOCID_A64) {
656 setbits_le32(&mctl_ctl->vtfcr, 2 << 8);
657 clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
658 }
Jens Kuske53f018e2015-11-17 15:12:59 +0100659
660 /* clear credit value */
661 setbits_le32(&mctl_com->cccr, 1 << 31);
662 udelay(10);
663
664 mctl_auto_detect_dram_size(&para);
665 mctl_set_cr(&para);
666
Andre Przywarad414c382017-01-02 11:48:44 +0000667 return (1UL << (para.row_bits + 3)) * para.page_size *
Jens Kuske53f018e2015-11-17 15:12:59 +0100668 (para.dual_rank ? 2 : 1);
669}