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