1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 MediaTek Inc.
4  *
5  * Author:  Weijie Gao <weijie.gao@mediatek.com>
6  */
7 
8 #include <common.h>
9 #include <linux/bitops.h>
10 #include <linux/delay.h>
11 #include <linux/io.h>
12 #include <linux/sizes.h>
13 #include <mach/ddr.h>
14 #include <mach/mc.h>
15 
16 #define DDR_BW_TEST_PAT			0xaa5555aa
17 
18 static const u32 sdr_size_cfg1[] = {
19 	[DRAM_8MB] = (1 << NUMROWS_S),
20 	[DRAM_16MB] = (1 << NUMROWS_S) | (1 << NUMCOLS_S),
21 	[DRAM_32MB] = (2 << NUMROWS_S) | (1 << NUMCOLS_S),
22 	[DRAM_64MB] = (2 << NUMROWS_S) | (2 << NUMCOLS_S),
23 };
24 
25 static const u32 dram_size[] = {
26 	[DRAM_8MB] = SZ_8M,
27 	[DRAM_16MB] = SZ_16M,
28 	[DRAM_32MB] = SZ_32M,
29 	[DRAM_64MB] = SZ_64M,
30 	[DRAM_128MB] = SZ_128M,
31 	[DRAM_256MB] = SZ_256M,
32 };
33 
dram_test_write(u32 addr,u32 val)34 static void dram_test_write(u32 addr, u32 val)
35 {
36 	volatile ulong *target = (volatile ulong *)(KSEG1 + addr);
37 
38 	sync();
39 	*target = val;
40 	sync();
41 }
42 
dram_test_read(u32 addr)43 static u32 dram_test_read(u32 addr)
44 {
45 	volatile ulong *target = (volatile ulong *)(KSEG1 + addr);
46 	u32 val;
47 
48 	sync();
49 	val = *target;
50 	sync();
51 
52 	return val;
53 }
54 
dram_addr_test_bit(u32 bit)55 static int dram_addr_test_bit(u32 bit)
56 {
57 	u32 val;
58 
59 	dram_test_write(0, 0);
60 	dram_test_write(BIT(bit), DDR_BW_TEST_PAT);
61 	val = dram_test_read(0);
62 
63 	if (val == DDR_BW_TEST_PAT)
64 		return 1;
65 
66 	return 0;
67 }
68 
mc_ddr_init(void __iomem * memc,const struct mc_ddr_cfg * cfg,u32 dq_dly,u32 dqs_dly,mc_reset_t mc_reset,u32 bw)69 static void mc_ddr_init(void __iomem *memc, const struct mc_ddr_cfg *cfg,
70 			u32 dq_dly, u32 dqs_dly, mc_reset_t mc_reset, u32 bw)
71 {
72 	u32 val;
73 
74 	mc_reset(1);
75 	__udelay(200);
76 	mc_reset(0);
77 
78 	clrbits_32(memc + MEMCTL_SDRAM_CFG1_REG, RBC_MAPPING);
79 
80 	writel(cfg->cfg2, memc + MEMCTL_DDR_CFG2_REG);
81 	writel(cfg->cfg3, memc + MEMCTL_DDR_CFG3_REG);
82 	writel(cfg->cfg4, memc + MEMCTL_DDR_CFG4_REG);
83 	writel(dq_dly, memc + MEMCTL_DDR_DQ_DLY_REG);
84 	writel(dqs_dly, memc + MEMCTL_DDR_DQS_DLY_REG);
85 
86 	writel(cfg->cfg0, memc + MEMCTL_DDR_CFG0_REG);
87 
88 	val = cfg->cfg1;
89 	if (bw) {
90 		val &= ~IND_SDRAM_WIDTH_M;
91 		val |= (bw << IND_SDRAM_WIDTH_S) & IND_SDRAM_WIDTH_M;
92 	}
93 
94 	writel(val, memc + MEMCTL_DDR_CFG1_REG);
95 
96 	clrsetbits_32(memc + MEMCTL_PWR_SAVE_CNT_REG, SR_TAR_CNT_M,
97 		      1 << SR_TAR_CNT_S);
98 
99 	setbits_32(memc + MEMCTL_DDR_SELF_REFRESH_REG, SR_AUTO_EN);
100 }
101 
ddr1_init(struct mc_ddr_init_param * param)102 void ddr1_init(struct mc_ddr_init_param *param)
103 {
104 	enum mc_dram_size sz;
105 	u32 bw = 0;
106 
107 	/* First initialization, determine bus width */
108 	mc_ddr_init(param->memc, &param->cfgs[DRAM_8MB], param->dq_dly,
109 		    param->dqs_dly, param->mc_reset, IND_SDRAM_WIDTH_16BIT);
110 
111 	/* Test bus width */
112 	dram_test_write(0, DDR_BW_TEST_PAT);
113 	if (dram_test_read(0) == DDR_BW_TEST_PAT)
114 		bw = IND_SDRAM_WIDTH_16BIT;
115 	else
116 		bw = IND_SDRAM_WIDTH_8BIT;
117 
118 	/* Second initialization, determine DDR capacity */
119 	mc_ddr_init(param->memc, &param->cfgs[DRAM_128MB], param->dq_dly,
120 		    param->dqs_dly, param->mc_reset, bw);
121 
122 	if (dram_addr_test_bit(9)) {
123 		sz = DRAM_8MB;
124 	} else {
125 		if (dram_addr_test_bit(10)) {
126 			if (dram_addr_test_bit(23))
127 				sz = DRAM_16MB;
128 			else
129 				sz = DRAM_32MB;
130 		} else {
131 			if (dram_addr_test_bit(24))
132 				sz = DRAM_64MB;
133 			else
134 				sz = DRAM_128MB;
135 		}
136 	}
137 
138 	/* Final initialization, with DDR calibration */
139 	mc_ddr_init(param->memc, &param->cfgs[sz], param->dq_dly,
140 		    param->dqs_dly, param->mc_reset, bw);
141 
142 	/* Return actual DDR configuration */
143 	param->memsize = dram_size[sz];
144 	param->bus_width = bw;
145 }
146 
ddr2_init(struct mc_ddr_init_param * param)147 void ddr2_init(struct mc_ddr_init_param *param)
148 {
149 	enum mc_dram_size sz;
150 	u32 bw = 0;
151 
152 	/* First initialization, determine bus width */
153 	mc_ddr_init(param->memc, &param->cfgs[DRAM_32MB], param->dq_dly,
154 		    param->dqs_dly, param->mc_reset, IND_SDRAM_WIDTH_16BIT);
155 
156 	/* Test bus width */
157 	dram_test_write(0, DDR_BW_TEST_PAT);
158 	if (dram_test_read(0) == DDR_BW_TEST_PAT)
159 		bw = IND_SDRAM_WIDTH_16BIT;
160 	else
161 		bw = IND_SDRAM_WIDTH_8BIT;
162 
163 	/* Second initialization, determine DDR capacity */
164 	mc_ddr_init(param->memc, &param->cfgs[DRAM_256MB], param->dq_dly,
165 		    param->dqs_dly, param->mc_reset, bw);
166 
167 	if (bw == IND_SDRAM_WIDTH_16BIT) {
168 		if (dram_addr_test_bit(10)) {
169 			sz = DRAM_32MB;
170 		} else {
171 			if (dram_addr_test_bit(24)) {
172 				if (dram_addr_test_bit(27))
173 					sz = DRAM_64MB;
174 				else
175 					sz = DRAM_128MB;
176 			} else {
177 				sz = DRAM_256MB;
178 			}
179 		}
180 	} else {
181 		if (dram_addr_test_bit(23)) {
182 			sz = DRAM_32MB;
183 		} else {
184 			if (dram_addr_test_bit(24)) {
185 				if (dram_addr_test_bit(27))
186 					sz = DRAM_64MB;
187 				else
188 					sz = DRAM_128MB;
189 			} else {
190 				sz = DRAM_256MB;
191 			}
192 		}
193 	}
194 
195 	/* Final initialization, with DDR calibration */
196 	mc_ddr_init(param->memc, &param->cfgs[sz], param->dq_dly,
197 		    param->dqs_dly, param->mc_reset, bw);
198 
199 	/* Return actual DDR configuration */
200 	param->memsize = dram_size[sz];
201 	param->bus_width = bw;
202 }
203 
mc_sdr_init(void __iomem * memc,mc_reset_t mc_reset,u32 cfg0,u32 cfg1)204 static void mc_sdr_init(void __iomem *memc, mc_reset_t mc_reset, u32 cfg0,
205 			u32 cfg1)
206 {
207 	mc_reset(1);
208 	__udelay(200);
209 	mc_reset(0);
210 
211 	writel(cfg0, memc + MEMCTL_SDRAM_CFG0_REG);
212 	writel(cfg1, memc + MEMCTL_SDRAM_CFG1_REG);
213 
214 	while (!(readl(memc + MEMCTL_SDRAM_CFG1_REG) & SDRAM_INIT_DONE))
215 		;
216 
217 	clrsetbits_32(memc + MEMCTL_PWR_SAVE_CNT_REG, SR_TAR_CNT_M,
218 		      1 << SR_TAR_CNT_S);
219 
220 	setbits_32(memc + MEMCTL_DDR_SELF_REFRESH_REG, SR_AUTO_EN);
221 }
222 
sdr_init(struct mc_ddr_init_param * param)223 void sdr_init(struct mc_ddr_init_param *param)
224 {
225 	enum mc_dram_size sz;
226 	u32 cfg1;
227 
228 	cfg1 = param->sdr_cfg1 | SDRAM_INIT_START;
229 	cfg1 &= ~(NUMCOLS_M | NUMROWS_M);
230 
231 	/* First initialization, determine SDR capacity */
232 	mc_sdr_init(param->memc, param->mc_reset, param->sdr_cfg0,
233 		    cfg1 | sdr_size_cfg1[DRAM_64MB]);
234 
235 	if (dram_addr_test_bit(9)) {
236 		sz = DRAM_8MB;
237 	} else {
238 		if (dram_addr_test_bit(10)) {
239 			if (dram_addr_test_bit(23))
240 				sz = DRAM_16MB;
241 			else
242 				sz = DRAM_32MB;
243 		} else {
244 			sz = DRAM_64MB;
245 		}
246 	}
247 
248 	/* Final initialization */
249 	mc_sdr_init(param->memc, param->mc_reset, param->sdr_cfg0,
250 		    cfg1 | sdr_size_cfg1[sz]);
251 
252 	/* Return actual DDR configuration */
253 	param->memsize = dram_size[sz];
254 }
255