xref: /linux/drivers/gpu/drm/ast/ast_2300.c (revision 0f336e9cffeef3c0655aca400a4574e0a140deeb)
1*0f336e9cSThomas Zimmermann // SPDX-License-Identifier: MIT
2*0f336e9cSThomas Zimmermann /*
3*0f336e9cSThomas Zimmermann  * Copyright 2012 Red Hat Inc.
4*0f336e9cSThomas Zimmermann  *
5*0f336e9cSThomas Zimmermann  * Permission is hereby granted, free of charge, to any person obtaining a
6*0f336e9cSThomas Zimmermann  * copy of this software and associated documentation files (the
7*0f336e9cSThomas Zimmermann  * "Software"), to deal in the Software without restriction, including
8*0f336e9cSThomas Zimmermann  * without limitation the rights to use, copy, modify, merge, publish,
9*0f336e9cSThomas Zimmermann  * distribute, sub license, and/or sell copies of the Software, and to
10*0f336e9cSThomas Zimmermann  * permit persons to whom the Software is furnished to do so, subject to
11*0f336e9cSThomas Zimmermann  * the following conditions:
12*0f336e9cSThomas Zimmermann  *
13*0f336e9cSThomas Zimmermann  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14*0f336e9cSThomas Zimmermann  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15*0f336e9cSThomas Zimmermann  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16*0f336e9cSThomas Zimmermann  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17*0f336e9cSThomas Zimmermann  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18*0f336e9cSThomas Zimmermann  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19*0f336e9cSThomas Zimmermann  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20*0f336e9cSThomas Zimmermann  *
21*0f336e9cSThomas Zimmermann  * The above copyright notice and this permission notice (including the
22*0f336e9cSThomas Zimmermann  * next paragraph) shall be included in all copies or substantial portions
23*0f336e9cSThomas Zimmermann  * of the Software.
24*0f336e9cSThomas Zimmermann  */
25*0f336e9cSThomas Zimmermann /*
26*0f336e9cSThomas Zimmermann  * Authors: Dave Airlie <airlied@redhat.com>
27*0f336e9cSThomas Zimmermann  */
28*0f336e9cSThomas Zimmermann 
29*0f336e9cSThomas Zimmermann #include <linux/delay.h>
30*0f336e9cSThomas Zimmermann 
31*0f336e9cSThomas Zimmermann #include "ast_drv.h"
32*0f336e9cSThomas Zimmermann #include "ast_post.h"
33*0f336e9cSThomas Zimmermann 
34*0f336e9cSThomas Zimmermann /*
35*0f336e9cSThomas Zimmermann  *  POST
36*0f336e9cSThomas Zimmermann  */
37*0f336e9cSThomas Zimmermann 
38*0f336e9cSThomas Zimmermann /* AST 2300 DRAM settings */
39*0f336e9cSThomas Zimmermann #define AST_DDR3 0
40*0f336e9cSThomas Zimmermann #define AST_DDR2 1
41*0f336e9cSThomas Zimmermann 
42*0f336e9cSThomas Zimmermann struct ast2300_dram_param {
43*0f336e9cSThomas Zimmermann 	u32 dram_type;
44*0f336e9cSThomas Zimmermann 	u32 dram_chipid;
45*0f336e9cSThomas Zimmermann 	u32 dram_freq;
46*0f336e9cSThomas Zimmermann 	u32 vram_size;
47*0f336e9cSThomas Zimmermann 	u32 odt;
48*0f336e9cSThomas Zimmermann 	u32 wodt;
49*0f336e9cSThomas Zimmermann 	u32 rodt;
50*0f336e9cSThomas Zimmermann 	u32 dram_config;
51*0f336e9cSThomas Zimmermann 	u32 reg_PERIOD;
52*0f336e9cSThomas Zimmermann 	u32 reg_MADJ;
53*0f336e9cSThomas Zimmermann 	u32 reg_SADJ;
54*0f336e9cSThomas Zimmermann 	u32 reg_MRS;
55*0f336e9cSThomas Zimmermann 	u32 reg_EMRS;
56*0f336e9cSThomas Zimmermann 	u32 reg_AC1;
57*0f336e9cSThomas Zimmermann 	u32 reg_AC2;
58*0f336e9cSThomas Zimmermann 	u32 reg_DQSIC;
59*0f336e9cSThomas Zimmermann 	u32 reg_DRV;
60*0f336e9cSThomas Zimmermann 	u32 reg_IOZ;
61*0f336e9cSThomas Zimmermann 	u32 reg_DQIDLY;
62*0f336e9cSThomas Zimmermann 	u32 reg_FREQ;
63*0f336e9cSThomas Zimmermann 	u32 madj_max;
64*0f336e9cSThomas Zimmermann 	u32 dll2_finetune_step;
65*0f336e9cSThomas Zimmermann };
66*0f336e9cSThomas Zimmermann 
67*0f336e9cSThomas Zimmermann /*
68*0f336e9cSThomas Zimmermann  * DQSI DLL CBR Setting
69*0f336e9cSThomas Zimmermann  */
70*0f336e9cSThomas Zimmermann #define CBR_SIZE0            ((1  << 10) - 1)
71*0f336e9cSThomas Zimmermann #define CBR_SIZE1            ((4  << 10) - 1)
72*0f336e9cSThomas Zimmermann #define CBR_SIZE2            ((64 << 10) - 1)
73*0f336e9cSThomas Zimmermann #define CBR_PASSNUM          5
74*0f336e9cSThomas Zimmermann #define CBR_PASSNUM2         5
75*0f336e9cSThomas Zimmermann #define CBR_THRESHOLD        10
76*0f336e9cSThomas Zimmermann #define CBR_THRESHOLD2       10
77*0f336e9cSThomas Zimmermann #define TIMEOUT              5000000
78*0f336e9cSThomas Zimmermann #define CBR_PATNUM           8
79*0f336e9cSThomas Zimmermann 
80*0f336e9cSThomas Zimmermann static const u32 pattern[8] = {
81*0f336e9cSThomas Zimmermann 	0xFF00FF00,
82*0f336e9cSThomas Zimmermann 	0xCC33CC33,
83*0f336e9cSThomas Zimmermann 	0xAA55AA55,
84*0f336e9cSThomas Zimmermann 	0x88778877,
85*0f336e9cSThomas Zimmermann 	0x92CC4D6E,
86*0f336e9cSThomas Zimmermann 	0x543D3CDE,
87*0f336e9cSThomas Zimmermann 	0xF1E843C7,
88*0f336e9cSThomas Zimmermann 	0x7C61D253
89*0f336e9cSThomas Zimmermann };
90*0f336e9cSThomas Zimmermann 
91*0f336e9cSThomas Zimmermann static u32 mmc_test2(struct ast_device *ast, u32 datagen, u8 test_ctl)
92*0f336e9cSThomas Zimmermann {
93*0f336e9cSThomas Zimmermann 	u32 data, timeout;
94*0f336e9cSThomas Zimmermann 
95*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
96*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
97*0f336e9cSThomas Zimmermann 	timeout = 0;
98*0f336e9cSThomas Zimmermann 	do {
99*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
100*0f336e9cSThomas Zimmermann 		if (++timeout > TIMEOUT) {
101*0f336e9cSThomas Zimmermann 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
102*0f336e9cSThomas Zimmermann 			return 0xffffffff;
103*0f336e9cSThomas Zimmermann 		}
104*0f336e9cSThomas Zimmermann 	} while (!data);
105*0f336e9cSThomas Zimmermann 	data = ast_mindwm(ast, 0x1e6e0078);
106*0f336e9cSThomas Zimmermann 	data = (data | (data >> 16)) & 0xffff;
107*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
108*0f336e9cSThomas Zimmermann 	return data;
109*0f336e9cSThomas Zimmermann }
110*0f336e9cSThomas Zimmermann 
111*0f336e9cSThomas Zimmermann static u32 mmc_test_burst2(struct ast_device *ast, u32 datagen)
112*0f336e9cSThomas Zimmermann {
113*0f336e9cSThomas Zimmermann 	return mmc_test2(ast, datagen, 0x41);
114*0f336e9cSThomas Zimmermann }
115*0f336e9cSThomas Zimmermann 
116*0f336e9cSThomas Zimmermann static bool mmc_test_single(struct ast_device *ast, u32 datagen)
117*0f336e9cSThomas Zimmermann {
118*0f336e9cSThomas Zimmermann 	return mmc_test(ast, datagen, 0xc5);
119*0f336e9cSThomas Zimmermann }
120*0f336e9cSThomas Zimmermann 
121*0f336e9cSThomas Zimmermann static u32 mmc_test_single2(struct ast_device *ast, u32 datagen)
122*0f336e9cSThomas Zimmermann {
123*0f336e9cSThomas Zimmermann 	return mmc_test2(ast, datagen, 0x05);
124*0f336e9cSThomas Zimmermann }
125*0f336e9cSThomas Zimmermann 
126*0f336e9cSThomas Zimmermann static int cbr_test(struct ast_device *ast)
127*0f336e9cSThomas Zimmermann {
128*0f336e9cSThomas Zimmermann 	u32 data;
129*0f336e9cSThomas Zimmermann 	int i;
130*0f336e9cSThomas Zimmermann 
131*0f336e9cSThomas Zimmermann 	data = mmc_test_single2(ast, 0);
132*0f336e9cSThomas Zimmermann 	if ((data & 0xff) && (data & 0xff00))
133*0f336e9cSThomas Zimmermann 		return 0;
134*0f336e9cSThomas Zimmermann 	for (i = 0; i < 8; i++) {
135*0f336e9cSThomas Zimmermann 		data = mmc_test_burst2(ast, i);
136*0f336e9cSThomas Zimmermann 		if ((data & 0xff) && (data & 0xff00))
137*0f336e9cSThomas Zimmermann 			return 0;
138*0f336e9cSThomas Zimmermann 	}
139*0f336e9cSThomas Zimmermann 	if (!data)
140*0f336e9cSThomas Zimmermann 		return 3;
141*0f336e9cSThomas Zimmermann 	else if (data & 0xff)
142*0f336e9cSThomas Zimmermann 		return 2;
143*0f336e9cSThomas Zimmermann 	return 1;
144*0f336e9cSThomas Zimmermann }
145*0f336e9cSThomas Zimmermann 
146*0f336e9cSThomas Zimmermann static int cbr_scan(struct ast_device *ast)
147*0f336e9cSThomas Zimmermann {
148*0f336e9cSThomas Zimmermann 	u32 data, data2, patcnt, loop;
149*0f336e9cSThomas Zimmermann 
150*0f336e9cSThomas Zimmermann 	data2 = 3;
151*0f336e9cSThomas Zimmermann 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
152*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
153*0f336e9cSThomas Zimmermann 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
154*0f336e9cSThomas Zimmermann 			data = cbr_test(ast);
155*0f336e9cSThomas Zimmermann 			if (data != 0) {
156*0f336e9cSThomas Zimmermann 				data2 &= data;
157*0f336e9cSThomas Zimmermann 				if (!data2)
158*0f336e9cSThomas Zimmermann 					return 0;
159*0f336e9cSThomas Zimmermann 				break;
160*0f336e9cSThomas Zimmermann 			}
161*0f336e9cSThomas Zimmermann 		}
162*0f336e9cSThomas Zimmermann 		if (loop == CBR_PASSNUM2)
163*0f336e9cSThomas Zimmermann 			return 0;
164*0f336e9cSThomas Zimmermann 	}
165*0f336e9cSThomas Zimmermann 	return data2;
166*0f336e9cSThomas Zimmermann }
167*0f336e9cSThomas Zimmermann 
168*0f336e9cSThomas Zimmermann static u32 cbr_test2(struct ast_device *ast)
169*0f336e9cSThomas Zimmermann {
170*0f336e9cSThomas Zimmermann 	u32 data;
171*0f336e9cSThomas Zimmermann 
172*0f336e9cSThomas Zimmermann 	data = mmc_test_burst2(ast, 0);
173*0f336e9cSThomas Zimmermann 	if (data == 0xffff)
174*0f336e9cSThomas Zimmermann 		return 0;
175*0f336e9cSThomas Zimmermann 	data |= mmc_test_single2(ast, 0);
176*0f336e9cSThomas Zimmermann 	if (data == 0xffff)
177*0f336e9cSThomas Zimmermann 		return 0;
178*0f336e9cSThomas Zimmermann 
179*0f336e9cSThomas Zimmermann 	return ~data & 0xffff;
180*0f336e9cSThomas Zimmermann }
181*0f336e9cSThomas Zimmermann 
182*0f336e9cSThomas Zimmermann static u32 cbr_scan2(struct ast_device *ast)
183*0f336e9cSThomas Zimmermann {
184*0f336e9cSThomas Zimmermann 	u32 data, data2, patcnt, loop;
185*0f336e9cSThomas Zimmermann 
186*0f336e9cSThomas Zimmermann 	data2 = 0xffff;
187*0f336e9cSThomas Zimmermann 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
188*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
189*0f336e9cSThomas Zimmermann 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
190*0f336e9cSThomas Zimmermann 			data = cbr_test2(ast);
191*0f336e9cSThomas Zimmermann 			if (data != 0) {
192*0f336e9cSThomas Zimmermann 				data2 &= data;
193*0f336e9cSThomas Zimmermann 				if (!data2)
194*0f336e9cSThomas Zimmermann 					return 0;
195*0f336e9cSThomas Zimmermann 				break;
196*0f336e9cSThomas Zimmermann 			}
197*0f336e9cSThomas Zimmermann 		}
198*0f336e9cSThomas Zimmermann 		if (loop == CBR_PASSNUM2)
199*0f336e9cSThomas Zimmermann 			return 0;
200*0f336e9cSThomas Zimmermann 	}
201*0f336e9cSThomas Zimmermann 	return data2;
202*0f336e9cSThomas Zimmermann }
203*0f336e9cSThomas Zimmermann 
204*0f336e9cSThomas Zimmermann static bool cbr_test3(struct ast_device *ast)
205*0f336e9cSThomas Zimmermann {
206*0f336e9cSThomas Zimmermann 	if (!mmc_test_burst(ast, 0))
207*0f336e9cSThomas Zimmermann 		return false;
208*0f336e9cSThomas Zimmermann 	if (!mmc_test_single(ast, 0))
209*0f336e9cSThomas Zimmermann 		return false;
210*0f336e9cSThomas Zimmermann 	return true;
211*0f336e9cSThomas Zimmermann }
212*0f336e9cSThomas Zimmermann 
213*0f336e9cSThomas Zimmermann static bool cbr_scan3(struct ast_device *ast)
214*0f336e9cSThomas Zimmermann {
215*0f336e9cSThomas Zimmermann 	u32 patcnt, loop;
216*0f336e9cSThomas Zimmermann 
217*0f336e9cSThomas Zimmermann 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
218*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
219*0f336e9cSThomas Zimmermann 		for (loop = 0; loop < 2; loop++) {
220*0f336e9cSThomas Zimmermann 			if (cbr_test3(ast))
221*0f336e9cSThomas Zimmermann 				break;
222*0f336e9cSThomas Zimmermann 		}
223*0f336e9cSThomas Zimmermann 		if (loop == 2)
224*0f336e9cSThomas Zimmermann 			return false;
225*0f336e9cSThomas Zimmermann 	}
226*0f336e9cSThomas Zimmermann 	return true;
227*0f336e9cSThomas Zimmermann }
228*0f336e9cSThomas Zimmermann 
229*0f336e9cSThomas Zimmermann static bool finetuneDQI_L(struct ast_device *ast, struct ast2300_dram_param *param)
230*0f336e9cSThomas Zimmermann {
231*0f336e9cSThomas Zimmermann 	u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
232*0f336e9cSThomas Zimmermann 	bool status = false;
233*0f336e9cSThomas Zimmermann FINETUNE_START:
234*0f336e9cSThomas Zimmermann 	for (cnt = 0; cnt < 16; cnt++) {
235*0f336e9cSThomas Zimmermann 		dllmin[cnt] = 0xff;
236*0f336e9cSThomas Zimmermann 		dllmax[cnt] = 0x0;
237*0f336e9cSThomas Zimmermann 	}
238*0f336e9cSThomas Zimmermann 	passcnt = 0;
239*0f336e9cSThomas Zimmermann 	for (dlli = 0; dlli < 76; dlli++) {
240*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24));
241*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
242*0f336e9cSThomas Zimmermann 		data = cbr_scan2(ast);
243*0f336e9cSThomas Zimmermann 		if (data != 0) {
244*0f336e9cSThomas Zimmermann 			mask = 0x00010001;
245*0f336e9cSThomas Zimmermann 			for (cnt = 0; cnt < 16; cnt++) {
246*0f336e9cSThomas Zimmermann 				if (data & mask) {
247*0f336e9cSThomas Zimmermann 					if (dllmin[cnt] > dlli)
248*0f336e9cSThomas Zimmermann 						dllmin[cnt] = dlli;
249*0f336e9cSThomas Zimmermann 					if (dllmax[cnt] < dlli)
250*0f336e9cSThomas Zimmermann 						dllmax[cnt] = dlli;
251*0f336e9cSThomas Zimmermann 				}
252*0f336e9cSThomas Zimmermann 				mask <<= 1;
253*0f336e9cSThomas Zimmermann 			}
254*0f336e9cSThomas Zimmermann 			passcnt++;
255*0f336e9cSThomas Zimmermann 		} else if (passcnt >= CBR_THRESHOLD2) {
256*0f336e9cSThomas Zimmermann 			break;
257*0f336e9cSThomas Zimmermann 		}
258*0f336e9cSThomas Zimmermann 	}
259*0f336e9cSThomas Zimmermann 	gold_sadj[0] = 0x0;
260*0f336e9cSThomas Zimmermann 	passcnt = 0;
261*0f336e9cSThomas Zimmermann 	for (cnt = 0; cnt < 16; cnt++) {
262*0f336e9cSThomas Zimmermann 		if ((dllmax[cnt] > dllmin[cnt]) &&
263*0f336e9cSThomas Zimmermann 		    ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
264*0f336e9cSThomas Zimmermann 			gold_sadj[0] += dllmin[cnt];
265*0f336e9cSThomas Zimmermann 			passcnt++;
266*0f336e9cSThomas Zimmermann 		}
267*0f336e9cSThomas Zimmermann 	}
268*0f336e9cSThomas Zimmermann 	if (retry++ > 10)
269*0f336e9cSThomas Zimmermann 		goto FINETUNE_DONE;
270*0f336e9cSThomas Zimmermann 	if (passcnt != 16)
271*0f336e9cSThomas Zimmermann 		goto FINETUNE_START;
272*0f336e9cSThomas Zimmermann 	status = true;
273*0f336e9cSThomas Zimmermann FINETUNE_DONE:
274*0f336e9cSThomas Zimmermann 	gold_sadj[0] = gold_sadj[0] >> 4;
275*0f336e9cSThomas Zimmermann 	gold_sadj[1] = gold_sadj[0];
276*0f336e9cSThomas Zimmermann 
277*0f336e9cSThomas Zimmermann 	data = 0;
278*0f336e9cSThomas Zimmermann 	for (cnt = 0; cnt < 8; cnt++) {
279*0f336e9cSThomas Zimmermann 		data >>= 3;
280*0f336e9cSThomas Zimmermann 		if ((dllmax[cnt] > dllmin[cnt]) &&
281*0f336e9cSThomas Zimmermann 		    ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
282*0f336e9cSThomas Zimmermann 			dlli = dllmin[cnt];
283*0f336e9cSThomas Zimmermann 			if (gold_sadj[0] >= dlli) {
284*0f336e9cSThomas Zimmermann 				dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
285*0f336e9cSThomas Zimmermann 				if (dlli > 3)
286*0f336e9cSThomas Zimmermann 					dlli = 3;
287*0f336e9cSThomas Zimmermann 			} else {
288*0f336e9cSThomas Zimmermann 				dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
289*0f336e9cSThomas Zimmermann 				if (dlli > 4)
290*0f336e9cSThomas Zimmermann 					dlli = 4;
291*0f336e9cSThomas Zimmermann 				dlli = (8 - dlli) & 0x7;
292*0f336e9cSThomas Zimmermann 			}
293*0f336e9cSThomas Zimmermann 			data |= dlli << 21;
294*0f336e9cSThomas Zimmermann 		}
295*0f336e9cSThomas Zimmermann 	}
296*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0080, data);
297*0f336e9cSThomas Zimmermann 
298*0f336e9cSThomas Zimmermann 	data = 0;
299*0f336e9cSThomas Zimmermann 	for (cnt = 8; cnt < 16; cnt++) {
300*0f336e9cSThomas Zimmermann 		data >>= 3;
301*0f336e9cSThomas Zimmermann 		if ((dllmax[cnt] > dllmin[cnt]) &&
302*0f336e9cSThomas Zimmermann 		    ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
303*0f336e9cSThomas Zimmermann 			dlli = dllmin[cnt];
304*0f336e9cSThomas Zimmermann 			if (gold_sadj[1] >= dlli) {
305*0f336e9cSThomas Zimmermann 				dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
306*0f336e9cSThomas Zimmermann 				if (dlli > 3)
307*0f336e9cSThomas Zimmermann 					dlli = 3;
308*0f336e9cSThomas Zimmermann 				else
309*0f336e9cSThomas Zimmermann 					dlli = (dlli - 1) & 0x7;
310*0f336e9cSThomas Zimmermann 			} else {
311*0f336e9cSThomas Zimmermann 				dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
312*0f336e9cSThomas Zimmermann 				dlli += 1;
313*0f336e9cSThomas Zimmermann 				if (dlli > 4)
314*0f336e9cSThomas Zimmermann 					dlli = 4;
315*0f336e9cSThomas Zimmermann 				dlli = (8 - dlli) & 0x7;
316*0f336e9cSThomas Zimmermann 			}
317*0f336e9cSThomas Zimmermann 			data |= dlli << 21;
318*0f336e9cSThomas Zimmermann 		}
319*0f336e9cSThomas Zimmermann 	}
320*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0084, data);
321*0f336e9cSThomas Zimmermann 	return status;
322*0f336e9cSThomas Zimmermann } /* finetuneDQI_L */
323*0f336e9cSThomas Zimmermann 
324*0f336e9cSThomas Zimmermann static void finetuneDQSI(struct ast_device *ast)
325*0f336e9cSThomas Zimmermann {
326*0f336e9cSThomas Zimmermann 	u32 dlli, dqsip, dqidly;
327*0f336e9cSThomas Zimmermann 	u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
328*0f336e9cSThomas Zimmermann 	u32 g_dqidly, g_dqsip, g_margin, g_side;
329*0f336e9cSThomas Zimmermann 	u16 pass[32][2][2];
330*0f336e9cSThomas Zimmermann 	char tag[2][76];
331*0f336e9cSThomas Zimmermann 
332*0f336e9cSThomas Zimmermann 	/* Disable DQI CBR */
333*0f336e9cSThomas Zimmermann 	reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
334*0f336e9cSThomas Zimmermann 	reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
335*0f336e9cSThomas Zimmermann 	reg_mcr18 &= 0x0000ffff;
336*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
337*0f336e9cSThomas Zimmermann 
338*0f336e9cSThomas Zimmermann 	for (dlli = 0; dlli < 76; dlli++) {
339*0f336e9cSThomas Zimmermann 		tag[0][dlli] = 0x0;
340*0f336e9cSThomas Zimmermann 		tag[1][dlli] = 0x0;
341*0f336e9cSThomas Zimmermann 	}
342*0f336e9cSThomas Zimmermann 	for (dqidly = 0; dqidly < 32; dqidly++) {
343*0f336e9cSThomas Zimmermann 		pass[dqidly][0][0] = 0xff;
344*0f336e9cSThomas Zimmermann 		pass[dqidly][0][1] = 0x0;
345*0f336e9cSThomas Zimmermann 		pass[dqidly][1][0] = 0xff;
346*0f336e9cSThomas Zimmermann 		pass[dqidly][1][1] = 0x0;
347*0f336e9cSThomas Zimmermann 	}
348*0f336e9cSThomas Zimmermann 	for (dqidly = 0; dqidly < 32; dqidly++) {
349*0f336e9cSThomas Zimmermann 		passcnt[0] = 0;
350*0f336e9cSThomas Zimmermann 		passcnt[1] = 0;
351*0f336e9cSThomas Zimmermann 		for (dqsip = 0; dqsip < 2; dqsip++) {
352*0f336e9cSThomas Zimmermann 			ast_moutdwm(ast, 0x1E6E000C, 0);
353*0f336e9cSThomas Zimmermann 			ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23));
354*0f336e9cSThomas Zimmermann 			ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
355*0f336e9cSThomas Zimmermann 			for (dlli = 0; dlli < 76; dlli++) {
356*0f336e9cSThomas Zimmermann 				ast_moutdwm(ast, 0x1E6E0068,
357*0f336e9cSThomas Zimmermann 					    0x00001300 | (dlli << 16) | (dlli << 24));
358*0f336e9cSThomas Zimmermann 				ast_moutdwm(ast, 0x1E6E0070, 0);
359*0f336e9cSThomas Zimmermann 				ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
360*0f336e9cSThomas Zimmermann 				if (cbr_scan3(ast)) {
361*0f336e9cSThomas Zimmermann 					if (dlli == 0)
362*0f336e9cSThomas Zimmermann 						break;
363*0f336e9cSThomas Zimmermann 					passcnt[dqsip]++;
364*0f336e9cSThomas Zimmermann 					tag[dqsip][dlli] = 'P';
365*0f336e9cSThomas Zimmermann 					if (dlli < pass[dqidly][dqsip][0])
366*0f336e9cSThomas Zimmermann 						pass[dqidly][dqsip][0] = (u16)dlli;
367*0f336e9cSThomas Zimmermann 					if (dlli > pass[dqidly][dqsip][1])
368*0f336e9cSThomas Zimmermann 						pass[dqidly][dqsip][1] = (u16)dlli;
369*0f336e9cSThomas Zimmermann 				} else if (passcnt[dqsip] >= 5) {
370*0f336e9cSThomas Zimmermann 					break;
371*0f336e9cSThomas Zimmermann 				} else {
372*0f336e9cSThomas Zimmermann 					pass[dqidly][dqsip][0] = 0xff;
373*0f336e9cSThomas Zimmermann 					pass[dqidly][dqsip][1] = 0x0;
374*0f336e9cSThomas Zimmermann 				}
375*0f336e9cSThomas Zimmermann 			}
376*0f336e9cSThomas Zimmermann 		}
377*0f336e9cSThomas Zimmermann 		if (passcnt[0] == 0 && passcnt[1] == 0)
378*0f336e9cSThomas Zimmermann 			dqidly++;
379*0f336e9cSThomas Zimmermann 	}
380*0f336e9cSThomas Zimmermann 	/* Search margin */
381*0f336e9cSThomas Zimmermann 	g_dqidly = 0;
382*0f336e9cSThomas Zimmermann 	g_dqsip = 0;
383*0f336e9cSThomas Zimmermann 	g_margin = 0;
384*0f336e9cSThomas Zimmermann 	g_side = 0;
385*0f336e9cSThomas Zimmermann 
386*0f336e9cSThomas Zimmermann 	for (dqidly = 0; dqidly < 32; dqidly++) {
387*0f336e9cSThomas Zimmermann 		for (dqsip = 0; dqsip < 2; dqsip++) {
388*0f336e9cSThomas Zimmermann 			if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
389*0f336e9cSThomas Zimmermann 				continue;
390*0f336e9cSThomas Zimmermann 			diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
391*0f336e9cSThomas Zimmermann 			if ((diff + 2) < g_margin)
392*0f336e9cSThomas Zimmermann 				continue;
393*0f336e9cSThomas Zimmermann 			passcnt[0] = 0;
394*0f336e9cSThomas Zimmermann 			passcnt[1] = 0;
395*0f336e9cSThomas Zimmermann 			for (dlli = pass[dqidly][dqsip][0];
396*0f336e9cSThomas Zimmermann 			     dlli > 0 && tag[dqsip][dlli] != 0;
397*0f336e9cSThomas Zimmermann 			     dlli--, passcnt[0]++) {
398*0f336e9cSThomas Zimmermann 			}
399*0f336e9cSThomas Zimmermann 			for (dlli = pass[dqidly][dqsip][1];
400*0f336e9cSThomas Zimmermann 			     dlli < 76 && tag[dqsip][dlli] != 0;
401*0f336e9cSThomas Zimmermann 			     dlli++, passcnt[1]++) {
402*0f336e9cSThomas Zimmermann 			}
403*0f336e9cSThomas Zimmermann 			if (passcnt[0] > passcnt[1])
404*0f336e9cSThomas Zimmermann 				passcnt[0] = passcnt[1];
405*0f336e9cSThomas Zimmermann 			passcnt[1] = 0;
406*0f336e9cSThomas Zimmermann 			if (passcnt[0] > g_side)
407*0f336e9cSThomas Zimmermann 				passcnt[1] = passcnt[0] - g_side;
408*0f336e9cSThomas Zimmermann 			if (diff > (g_margin + 1) && (passcnt[1] > 0 || passcnt[0] > 8)) {
409*0f336e9cSThomas Zimmermann 				g_margin = diff;
410*0f336e9cSThomas Zimmermann 				g_dqidly = dqidly;
411*0f336e9cSThomas Zimmermann 				g_dqsip  = dqsip;
412*0f336e9cSThomas Zimmermann 				g_side   = passcnt[0];
413*0f336e9cSThomas Zimmermann 			} else if (passcnt[1] > 1 && g_side < 8) {
414*0f336e9cSThomas Zimmermann 				if (diff > g_margin)
415*0f336e9cSThomas Zimmermann 					g_margin = diff;
416*0f336e9cSThomas Zimmermann 				g_dqidly = dqidly;
417*0f336e9cSThomas Zimmermann 				g_dqsip  = dqsip;
418*0f336e9cSThomas Zimmermann 				g_side   = passcnt[0];
419*0f336e9cSThomas Zimmermann 			}
420*0f336e9cSThomas Zimmermann 		}
421*0f336e9cSThomas Zimmermann 	}
422*0f336e9cSThomas Zimmermann 	reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
423*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
424*0f336e9cSThomas Zimmermann }
425*0f336e9cSThomas Zimmermann 
426*0f336e9cSThomas Zimmermann static bool cbr_dll2(struct ast_device *ast, struct ast2300_dram_param *param)
427*0f336e9cSThomas Zimmermann {
428*0f336e9cSThomas Zimmermann 	u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
429*0f336e9cSThomas Zimmermann 	bool status = false;
430*0f336e9cSThomas Zimmermann 
431*0f336e9cSThomas Zimmermann 	finetuneDQSI(ast);
432*0f336e9cSThomas Zimmermann 	if (finetuneDQI_L(ast, param) == false)
433*0f336e9cSThomas Zimmermann 		return status;
434*0f336e9cSThomas Zimmermann 
435*0f336e9cSThomas Zimmermann CBR_START2:
436*0f336e9cSThomas Zimmermann 	dllmin[0] = 0xff;
437*0f336e9cSThomas Zimmermann 	dllmin[1] = 0xff;
438*0f336e9cSThomas Zimmermann 	dllmax[0] = 0x0;
439*0f336e9cSThomas Zimmermann 	dllmax[1] = 0x0;
440*0f336e9cSThomas Zimmermann 	passcnt = 0;
441*0f336e9cSThomas Zimmermann 	for (dlli = 0; dlli < 76; dlli++) {
442*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
443*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
444*0f336e9cSThomas Zimmermann 		data = cbr_scan(ast);
445*0f336e9cSThomas Zimmermann 		if (data != 0) {
446*0f336e9cSThomas Zimmermann 			if (data & 0x1) {
447*0f336e9cSThomas Zimmermann 				if (dllmin[0] > dlli)
448*0f336e9cSThomas Zimmermann 					dllmin[0] = dlli;
449*0f336e9cSThomas Zimmermann 				if (dllmax[0] < dlli)
450*0f336e9cSThomas Zimmermann 					dllmax[0] = dlli;
451*0f336e9cSThomas Zimmermann 			}
452*0f336e9cSThomas Zimmermann 			if (data & 0x2) {
453*0f336e9cSThomas Zimmermann 				if (dllmin[1] > dlli)
454*0f336e9cSThomas Zimmermann 					dllmin[1] = dlli;
455*0f336e9cSThomas Zimmermann 				if (dllmax[1] < dlli)
456*0f336e9cSThomas Zimmermann 					dllmax[1] = dlli;
457*0f336e9cSThomas Zimmermann 			}
458*0f336e9cSThomas Zimmermann 			passcnt++;
459*0f336e9cSThomas Zimmermann 		} else if (passcnt >= CBR_THRESHOLD) {
460*0f336e9cSThomas Zimmermann 			break;
461*0f336e9cSThomas Zimmermann 		}
462*0f336e9cSThomas Zimmermann 	}
463*0f336e9cSThomas Zimmermann 	if (retry++ > 10)
464*0f336e9cSThomas Zimmermann 		goto CBR_DONE2;
465*0f336e9cSThomas Zimmermann 	if (dllmax[0] == 0 || (dllmax[0] - dllmin[0]) < CBR_THRESHOLD)
466*0f336e9cSThomas Zimmermann 		goto CBR_START2;
467*0f336e9cSThomas Zimmermann 	if (dllmax[1] == 0 || (dllmax[1] - dllmin[1]) < CBR_THRESHOLD)
468*0f336e9cSThomas Zimmermann 		goto CBR_START2;
469*0f336e9cSThomas Zimmermann 	status = true;
470*0f336e9cSThomas Zimmermann CBR_DONE2:
471*0f336e9cSThomas Zimmermann 	dlli  = (dllmin[1] + dllmax[1]) >> 1;
472*0f336e9cSThomas Zimmermann 	dlli <<= 8;
473*0f336e9cSThomas Zimmermann 	dlli += (dllmin[0] + dllmax[0]) >> 1;
474*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16));
475*0f336e9cSThomas Zimmermann 	return status;
476*0f336e9cSThomas Zimmermann } /* CBRDLL2 */
477*0f336e9cSThomas Zimmermann 
478*0f336e9cSThomas Zimmermann static void get_ddr3_info(struct ast_device *ast, struct ast2300_dram_param *param)
479*0f336e9cSThomas Zimmermann {
480*0f336e9cSThomas Zimmermann 	u32 trap, trap_AC2, trap_MRS;
481*0f336e9cSThomas Zimmermann 
482*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
483*0f336e9cSThomas Zimmermann 
484*0f336e9cSThomas Zimmermann 	/* Ger trap info */
485*0f336e9cSThomas Zimmermann 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
486*0f336e9cSThomas Zimmermann 	trap_AC2  = 0x00020000 + (trap << 16);
487*0f336e9cSThomas Zimmermann 	trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
488*0f336e9cSThomas Zimmermann 	trap_MRS  = 0x00000010 + (trap << 4);
489*0f336e9cSThomas Zimmermann 	trap_MRS |= ((trap & 0x2) << 18);
490*0f336e9cSThomas Zimmermann 
491*0f336e9cSThomas Zimmermann 	param->reg_MADJ       = 0x00034C4C;
492*0f336e9cSThomas Zimmermann 	param->reg_SADJ       = 0x00001800;
493*0f336e9cSThomas Zimmermann 	param->reg_DRV        = 0x000000F0;
494*0f336e9cSThomas Zimmermann 	param->reg_PERIOD     = param->dram_freq;
495*0f336e9cSThomas Zimmermann 	param->rodt           = 0;
496*0f336e9cSThomas Zimmermann 
497*0f336e9cSThomas Zimmermann 	switch (param->dram_freq) {
498*0f336e9cSThomas Zimmermann 	case 336:
499*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
500*0f336e9cSThomas Zimmermann 		param->wodt          = 0;
501*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x22202725;
502*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xAA007613 | trap_AC2;
503*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000BA;
504*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x04001400 | trap_MRS;
505*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000000;
506*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000023;
507*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000074;
508*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x00004DC0;
509*0f336e9cSThomas Zimmermann 		param->madj_max      = 96;
510*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
511*0f336e9cSThomas Zimmermann 		switch (param->dram_chipid) {
512*0f336e9cSThomas Zimmermann 		default:
513*0f336e9cSThomas Zimmermann 		case AST_DRAM_512Mx16:
514*0f336e9cSThomas Zimmermann 		case AST_DRAM_1Gx16:
515*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xAA007613 | trap_AC2;
516*0f336e9cSThomas Zimmermann 			break;
517*0f336e9cSThomas Zimmermann 		case AST_DRAM_2Gx16:
518*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xAA00761C | trap_AC2;
519*0f336e9cSThomas Zimmermann 			break;
520*0f336e9cSThomas Zimmermann 		case AST_DRAM_4Gx16:
521*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xAA007636 | trap_AC2;
522*0f336e9cSThomas Zimmermann 			break;
523*0f336e9cSThomas Zimmermann 		}
524*0f336e9cSThomas Zimmermann 		break;
525*0f336e9cSThomas Zimmermann 	default:
526*0f336e9cSThomas Zimmermann 	case 396:
527*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
528*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
529*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302825;
530*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xCC009617 | trap_AC2;
531*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000E2;
532*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x04001600 | trap_MRS;
533*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000000;
534*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000034;
535*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000FA;
536*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000089;
537*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x00005040;
538*0f336e9cSThomas Zimmermann 		param->madj_max      = 96;
539*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 4;
540*0f336e9cSThomas Zimmermann 
541*0f336e9cSThomas Zimmermann 		switch (param->dram_chipid) {
542*0f336e9cSThomas Zimmermann 		default:
543*0f336e9cSThomas Zimmermann 		case AST_DRAM_512Mx16:
544*0f336e9cSThomas Zimmermann 		case AST_DRAM_1Gx16:
545*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC009617 | trap_AC2;
546*0f336e9cSThomas Zimmermann 			break;
547*0f336e9cSThomas Zimmermann 		case AST_DRAM_2Gx16:
548*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC009622 | trap_AC2;
549*0f336e9cSThomas Zimmermann 			break;
550*0f336e9cSThomas Zimmermann 		case AST_DRAM_4Gx16:
551*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00963F | trap_AC2;
552*0f336e9cSThomas Zimmermann 			break;
553*0f336e9cSThomas Zimmermann 		}
554*0f336e9cSThomas Zimmermann 		break;
555*0f336e9cSThomas Zimmermann 
556*0f336e9cSThomas Zimmermann 	case 408:
557*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
558*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
559*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302825;
560*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xCC009617 | trap_AC2;
561*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000E2;
562*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x04001600 | trap_MRS;
563*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000000;
564*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000023;
565*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000FA;
566*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000089;
567*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000050C0;
568*0f336e9cSThomas Zimmermann 		param->madj_max      = 96;
569*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 4;
570*0f336e9cSThomas Zimmermann 
571*0f336e9cSThomas Zimmermann 		switch (param->dram_chipid) {
572*0f336e9cSThomas Zimmermann 		default:
573*0f336e9cSThomas Zimmermann 		case AST_DRAM_512Mx16:
574*0f336e9cSThomas Zimmermann 		case AST_DRAM_1Gx16:
575*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC009617 | trap_AC2;
576*0f336e9cSThomas Zimmermann 			break;
577*0f336e9cSThomas Zimmermann 		case AST_DRAM_2Gx16:
578*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC009622 | trap_AC2;
579*0f336e9cSThomas Zimmermann 			break;
580*0f336e9cSThomas Zimmermann 		case AST_DRAM_4Gx16:
581*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00963F | trap_AC2;
582*0f336e9cSThomas Zimmermann 			break;
583*0f336e9cSThomas Zimmermann 		}
584*0f336e9cSThomas Zimmermann 
585*0f336e9cSThomas Zimmermann 		break;
586*0f336e9cSThomas Zimmermann 	case 456:
587*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
588*0f336e9cSThomas Zimmermann 		param->wodt          = 0;
589*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302926;
590*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xCD44961A;
591*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000FC;
592*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00081830;
593*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000000;
594*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000045;
595*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000097;
596*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000052C0;
597*0f336e9cSThomas Zimmermann 		param->madj_max      = 88;
598*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 4;
599*0f336e9cSThomas Zimmermann 		break;
600*0f336e9cSThomas Zimmermann 	case 504:
601*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0270);
602*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
603*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302926;
604*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xDE44A61D;
605*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x00000117;
606*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00081A30;
607*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000000;
608*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x070000BB;
609*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x000000A0;
610*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000054C0;
611*0f336e9cSThomas Zimmermann 		param->madj_max      = 79;
612*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 4;
613*0f336e9cSThomas Zimmermann 		break;
614*0f336e9cSThomas Zimmermann 	case 528:
615*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0290);
616*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
617*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
618*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302926;
619*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xEF44B61E;
620*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x00000125;
621*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00081A30;
622*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000040;
623*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000F5;
624*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000023;
625*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000088;
626*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000055C0;
627*0f336e9cSThomas Zimmermann 		param->madj_max      = 76;
628*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
629*0f336e9cSThomas Zimmermann 		break;
630*0f336e9cSThomas Zimmermann 	case 576:
631*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
632*0f336e9cSThomas Zimmermann 		param->reg_MADJ      = 0x00136868;
633*0f336e9cSThomas Zimmermann 		param->reg_SADJ      = 0x00004534;
634*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
635*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
636*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302A37;
637*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xEF56B61E;
638*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x0000013F;
639*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00101A50;
640*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000040;
641*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000FA;
642*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000023;
643*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000078;
644*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000057C0;
645*0f336e9cSThomas Zimmermann 		param->madj_max      = 136;
646*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
647*0f336e9cSThomas Zimmermann 		break;
648*0f336e9cSThomas Zimmermann 	case 600:
649*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
650*0f336e9cSThomas Zimmermann 		param->reg_MADJ      = 0x00136868;
651*0f336e9cSThomas Zimmermann 		param->reg_SADJ      = 0x00004534;
652*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
653*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
654*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x32302A37;
655*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xDF56B61F;
656*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x0000014D;
657*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00101A50;
658*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000004;
659*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000F5;
660*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000023;
661*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000078;
662*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000058C0;
663*0f336e9cSThomas Zimmermann 		param->madj_max      = 132;
664*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
665*0f336e9cSThomas Zimmermann 		break;
666*0f336e9cSThomas Zimmermann 	case 624:
667*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0160);
668*0f336e9cSThomas Zimmermann 		param->reg_MADJ      = 0x00136868;
669*0f336e9cSThomas Zimmermann 		param->reg_SADJ      = 0x00004534;
670*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
671*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
672*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x32302A37;
673*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xEF56B621;
674*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x0000015A;
675*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x02101A50;
676*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000004;
677*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000F5;
678*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000034;
679*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000078;
680*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000059C0;
681*0f336e9cSThomas Zimmermann 		param->madj_max      = 128;
682*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
683*0f336e9cSThomas Zimmermann 		break;
684*0f336e9cSThomas Zimmermann 	} /* switch freq */
685*0f336e9cSThomas Zimmermann 
686*0f336e9cSThomas Zimmermann 	switch (param->dram_chipid) {
687*0f336e9cSThomas Zimmermann 	case AST_DRAM_512Mx16:
688*0f336e9cSThomas Zimmermann 		param->dram_config = 0x130;
689*0f336e9cSThomas Zimmermann 		break;
690*0f336e9cSThomas Zimmermann 	default:
691*0f336e9cSThomas Zimmermann 	case AST_DRAM_1Gx16:
692*0f336e9cSThomas Zimmermann 		param->dram_config = 0x131;
693*0f336e9cSThomas Zimmermann 		break;
694*0f336e9cSThomas Zimmermann 	case AST_DRAM_2Gx16:
695*0f336e9cSThomas Zimmermann 		param->dram_config = 0x132;
696*0f336e9cSThomas Zimmermann 		break;
697*0f336e9cSThomas Zimmermann 	case AST_DRAM_4Gx16:
698*0f336e9cSThomas Zimmermann 		param->dram_config = 0x133;
699*0f336e9cSThomas Zimmermann 		break;
700*0f336e9cSThomas Zimmermann 	} /* switch size */
701*0f336e9cSThomas Zimmermann 
702*0f336e9cSThomas Zimmermann 	switch (param->vram_size) {
703*0f336e9cSThomas Zimmermann 	default:
704*0f336e9cSThomas Zimmermann 	case SZ_8M:
705*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x00;
706*0f336e9cSThomas Zimmermann 		break;
707*0f336e9cSThomas Zimmermann 	case SZ_16M:
708*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x04;
709*0f336e9cSThomas Zimmermann 		break;
710*0f336e9cSThomas Zimmermann 	case SZ_32M:
711*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x08;
712*0f336e9cSThomas Zimmermann 		break;
713*0f336e9cSThomas Zimmermann 	case SZ_64M:
714*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x0c;
715*0f336e9cSThomas Zimmermann 		break;
716*0f336e9cSThomas Zimmermann 	}
717*0f336e9cSThomas Zimmermann }
718*0f336e9cSThomas Zimmermann 
719*0f336e9cSThomas Zimmermann static void ddr3_init(struct ast_device *ast, struct ast2300_dram_param *param)
720*0f336e9cSThomas Zimmermann {
721*0f336e9cSThomas Zimmermann 	u32 data, data2, retry = 0;
722*0f336e9cSThomas Zimmermann 
723*0f336e9cSThomas Zimmermann ddr3_init_start:
724*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
725*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
726*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
727*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
728*0f336e9cSThomas Zimmermann 	udelay(10);
729*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
730*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
731*0f336e9cSThomas Zimmermann 	udelay(10);
732*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
733*0f336e9cSThomas Zimmermann 	udelay(10);
734*0f336e9cSThomas Zimmermann 
735*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
736*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
737*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
738*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
739*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
740*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
741*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
742*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
743*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
744*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
745*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
746*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
747*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
748*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
749*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
750*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
751*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
752*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0054, 0);
753*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
754*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
755*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
756*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
757*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
758*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
759*0f336e9cSThomas Zimmermann 	/* Wait MCLK2X lock to MCLK */
760*0f336e9cSThomas Zimmermann 	do {
761*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E001C);
762*0f336e9cSThomas Zimmermann 	} while (!(data & 0x08000000));
763*0f336e9cSThomas Zimmermann 	data = ast_mindwm(ast, 0x1E6E001C);
764*0f336e9cSThomas Zimmermann 	data = (data >> 8) & 0xff;
765*0f336e9cSThomas Zimmermann 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
766*0f336e9cSThomas Zimmermann 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
767*0f336e9cSThomas Zimmermann 		if ((data2 & 0xff) > param->madj_max)
768*0f336e9cSThomas Zimmermann 			break;
769*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0064, data2);
770*0f336e9cSThomas Zimmermann 		if (data2 & 0x00100000)
771*0f336e9cSThomas Zimmermann 			data2 = ((data2 & 0xff) >> 3) + 3;
772*0f336e9cSThomas Zimmermann 		else
773*0f336e9cSThomas Zimmermann 			data2 = ((data2 & 0xff) >> 2) + 5;
774*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
775*0f336e9cSThomas Zimmermann 		data2 += data & 0xff;
776*0f336e9cSThomas Zimmermann 		data = data | (data2 << 8);
777*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0068, data);
778*0f336e9cSThomas Zimmermann 		udelay(10);
779*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
780*0f336e9cSThomas Zimmermann 		udelay(10);
781*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
782*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0018, data);
783*0f336e9cSThomas Zimmermann 		data = data | 0x200;
784*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0018, data);
785*0f336e9cSThomas Zimmermann 		do {
786*0f336e9cSThomas Zimmermann 			data = ast_mindwm(ast, 0x1E6E001C);
787*0f336e9cSThomas Zimmermann 		} while (!(data & 0x08000000));
788*0f336e9cSThomas Zimmermann 
789*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E001C);
790*0f336e9cSThomas Zimmermann 		data = (data >> 8) & 0xff;
791*0f336e9cSThomas Zimmermann 	}
792*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
793*0f336e9cSThomas Zimmermann 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
794*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, data);
795*0f336e9cSThomas Zimmermann 
796*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
797*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
798*0f336e9cSThomas Zimmermann 	udelay(50);
799*0f336e9cSThomas Zimmermann 	/* Mode Register Setting */
800*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
801*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
802*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
803*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
804*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
805*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
806*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
807*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
808*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
809*0f336e9cSThomas Zimmermann 
810*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
811*0f336e9cSThomas Zimmermann 	data = 0;
812*0f336e9cSThomas Zimmermann 	if (param->wodt)
813*0f336e9cSThomas Zimmermann 		data = 0x300;
814*0f336e9cSThomas Zimmermann 	if (param->rodt)
815*0f336e9cSThomas Zimmermann 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
816*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
817*0f336e9cSThomas Zimmermann 
818*0f336e9cSThomas Zimmermann 	/* Calibrate the DQSI delay */
819*0f336e9cSThomas Zimmermann 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
820*0f336e9cSThomas Zimmermann 		goto ddr3_init_start;
821*0f336e9cSThomas Zimmermann 
822*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
823*0f336e9cSThomas Zimmermann 	/* ECC Memory Initialization */
824*0f336e9cSThomas Zimmermann #ifdef ECC
825*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
826*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
827*0f336e9cSThomas Zimmermann 	do {
828*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E0070);
829*0f336e9cSThomas Zimmermann 	} while (!(data & 0x00001000));
830*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
831*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
832*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
833*0f336e9cSThomas Zimmermann #endif
834*0f336e9cSThomas Zimmermann }
835*0f336e9cSThomas Zimmermann 
836*0f336e9cSThomas Zimmermann static void get_ddr2_info(struct ast_device *ast, struct ast2300_dram_param *param)
837*0f336e9cSThomas Zimmermann {
838*0f336e9cSThomas Zimmermann 	u32 trap, trap_AC2, trap_MRS;
839*0f336e9cSThomas Zimmermann 
840*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
841*0f336e9cSThomas Zimmermann 
842*0f336e9cSThomas Zimmermann 	/* Ger trap info */
843*0f336e9cSThomas Zimmermann 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
844*0f336e9cSThomas Zimmermann 	trap_AC2  = (trap << 20) | (trap << 16);
845*0f336e9cSThomas Zimmermann 	trap_AC2 += 0x00110000;
846*0f336e9cSThomas Zimmermann 	trap_MRS  = 0x00000040 | (trap << 4);
847*0f336e9cSThomas Zimmermann 
848*0f336e9cSThomas Zimmermann 	param->reg_MADJ       = 0x00034C4C;
849*0f336e9cSThomas Zimmermann 	param->reg_SADJ       = 0x00001800;
850*0f336e9cSThomas Zimmermann 	param->reg_DRV        = 0x000000F0;
851*0f336e9cSThomas Zimmermann 	param->reg_PERIOD     = param->dram_freq;
852*0f336e9cSThomas Zimmermann 	param->rodt           = 0;
853*0f336e9cSThomas Zimmermann 
854*0f336e9cSThomas Zimmermann 	switch (param->dram_freq) {
855*0f336e9cSThomas Zimmermann 	case 264:
856*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0130);
857*0f336e9cSThomas Zimmermann 		param->wodt          = 0;
858*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x11101513;
859*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0x78117011;
860*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x00000092;
861*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000842;
862*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000000;
863*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000F0;
864*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000034;
865*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x0000005A;
866*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x00004AC0;
867*0f336e9cSThomas Zimmermann 		param->madj_max      = 138;
868*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
869*0f336e9cSThomas Zimmermann 		break;
870*0f336e9cSThomas Zimmermann 	case 336:
871*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
872*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
873*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x22202613;
874*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xAA009016 | trap_AC2;
875*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000BA;
876*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000A02 | trap_MRS;
877*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000040;
878*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000FA;
879*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000034;
880*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000074;
881*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x00004DC0;
882*0f336e9cSThomas Zimmermann 		param->madj_max      = 96;
883*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
884*0f336e9cSThomas Zimmermann 		switch (param->dram_chipid) {
885*0f336e9cSThomas Zimmermann 		default:
886*0f336e9cSThomas Zimmermann 		case AST_DRAM_512Mx16:
887*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xAA009012 | trap_AC2;
888*0f336e9cSThomas Zimmermann 			break;
889*0f336e9cSThomas Zimmermann 		case AST_DRAM_1Gx16:
890*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xAA009016 | trap_AC2;
891*0f336e9cSThomas Zimmermann 			break;
892*0f336e9cSThomas Zimmermann 		case AST_DRAM_2Gx16:
893*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xAA009023 | trap_AC2;
894*0f336e9cSThomas Zimmermann 			break;
895*0f336e9cSThomas Zimmermann 		case AST_DRAM_4Gx16:
896*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xAA00903B | trap_AC2;
897*0f336e9cSThomas Zimmermann 			break;
898*0f336e9cSThomas Zimmermann 		}
899*0f336e9cSThomas Zimmermann 		break;
900*0f336e9cSThomas Zimmermann 	default:
901*0f336e9cSThomas Zimmermann 	case 396:
902*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
903*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
904*0f336e9cSThomas Zimmermann 		param->rodt          = 0;
905*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302714;
906*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
907*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000E2;
908*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000C02 | trap_MRS;
909*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000040;
910*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000FA;
911*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000034;
912*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000089;
913*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x00005040;
914*0f336e9cSThomas Zimmermann 		param->madj_max      = 96;
915*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 4;
916*0f336e9cSThomas Zimmermann 
917*0f336e9cSThomas Zimmermann 		switch (param->dram_chipid) {
918*0f336e9cSThomas Zimmermann 		case AST_DRAM_512Mx16:
919*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
920*0f336e9cSThomas Zimmermann 			break;
921*0f336e9cSThomas Zimmermann 		default:
922*0f336e9cSThomas Zimmermann 		case AST_DRAM_1Gx16:
923*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
924*0f336e9cSThomas Zimmermann 			break;
925*0f336e9cSThomas Zimmermann 		case AST_DRAM_2Gx16:
926*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
927*0f336e9cSThomas Zimmermann 			break;
928*0f336e9cSThomas Zimmermann 		case AST_DRAM_4Gx16:
929*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
930*0f336e9cSThomas Zimmermann 			break;
931*0f336e9cSThomas Zimmermann 		}
932*0f336e9cSThomas Zimmermann 
933*0f336e9cSThomas Zimmermann 		break;
934*0f336e9cSThomas Zimmermann 
935*0f336e9cSThomas Zimmermann 	case 408:
936*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
937*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
938*0f336e9cSThomas Zimmermann 		param->rodt          = 0;
939*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302714;
940*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
941*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000E2;
942*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000C02 | trap_MRS;
943*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000040;
944*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000FA;
945*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000034;
946*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000089;
947*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000050C0;
948*0f336e9cSThomas Zimmermann 		param->madj_max      = 96;
949*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 4;
950*0f336e9cSThomas Zimmermann 
951*0f336e9cSThomas Zimmermann 		switch (param->dram_chipid) {
952*0f336e9cSThomas Zimmermann 		case AST_DRAM_512Mx16:
953*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
954*0f336e9cSThomas Zimmermann 			break;
955*0f336e9cSThomas Zimmermann 		default:
956*0f336e9cSThomas Zimmermann 		case AST_DRAM_1Gx16:
957*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
958*0f336e9cSThomas Zimmermann 			break;
959*0f336e9cSThomas Zimmermann 		case AST_DRAM_2Gx16:
960*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
961*0f336e9cSThomas Zimmermann 			break;
962*0f336e9cSThomas Zimmermann 		case AST_DRAM_4Gx16:
963*0f336e9cSThomas Zimmermann 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
964*0f336e9cSThomas Zimmermann 			break;
965*0f336e9cSThomas Zimmermann 		}
966*0f336e9cSThomas Zimmermann 
967*0f336e9cSThomas Zimmermann 		break;
968*0f336e9cSThomas Zimmermann 	case 456:
969*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
970*0f336e9cSThomas Zimmermann 		param->wodt          = 0;
971*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302815;
972*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xCD44B01E;
973*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x000000FC;
974*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000E72;
975*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000000;
976*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x00000000;
977*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000034;
978*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x00000097;
979*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000052C0;
980*0f336e9cSThomas Zimmermann 		param->madj_max      = 88;
981*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
982*0f336e9cSThomas Zimmermann 		break;
983*0f336e9cSThomas Zimmermann 	case 504:
984*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0261);
985*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
986*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
987*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302815;
988*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xDE44C022;
989*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x00000117;
990*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000E72;
991*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000040;
992*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x0000000A;
993*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000045;
994*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x000000A0;
995*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000054C0;
996*0f336e9cSThomas Zimmermann 		param->madj_max      = 79;
997*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
998*0f336e9cSThomas Zimmermann 		break;
999*0f336e9cSThomas Zimmermann 	case 528:
1000*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0120);
1001*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
1002*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
1003*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x33302815;
1004*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xEF44D024;
1005*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x00000125;
1006*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000E72;
1007*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000004;
1008*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000F9;
1009*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000045;
1010*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x000000A7;
1011*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000055C0;
1012*0f336e9cSThomas Zimmermann 		param->madj_max      = 76;
1013*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
1014*0f336e9cSThomas Zimmermann 		break;
1015*0f336e9cSThomas Zimmermann 	case 552:
1016*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
1017*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
1018*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
1019*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x43402915;
1020*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xFF44E025;
1021*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x00000132;
1022*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000E72;
1023*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000040;
1024*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x0000000A;
1025*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000045;
1026*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x000000AD;
1027*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000056C0;
1028*0f336e9cSThomas Zimmermann 		param->madj_max      = 76;
1029*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
1030*0f336e9cSThomas Zimmermann 		break;
1031*0f336e9cSThomas Zimmermann 	case 576:
1032*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1033*0f336e9cSThomas Zimmermann 		param->wodt          = 1;
1034*0f336e9cSThomas Zimmermann 		param->rodt          = 1;
1035*0f336e9cSThomas Zimmermann 		param->reg_AC1       = 0x43402915;
1036*0f336e9cSThomas Zimmermann 		param->reg_AC2       = 0xFF44E027;
1037*0f336e9cSThomas Zimmermann 		param->reg_DQSIC     = 0x0000013F;
1038*0f336e9cSThomas Zimmermann 		param->reg_MRS       = 0x00000E72;
1039*0f336e9cSThomas Zimmermann 		param->reg_EMRS      = 0x00000004;
1040*0f336e9cSThomas Zimmermann 		param->reg_DRV       = 0x000000F5;
1041*0f336e9cSThomas Zimmermann 		param->reg_IOZ       = 0x00000045;
1042*0f336e9cSThomas Zimmermann 		param->reg_DQIDLY    = 0x000000B3;
1043*0f336e9cSThomas Zimmermann 		param->reg_FREQ      = 0x000057C0;
1044*0f336e9cSThomas Zimmermann 		param->madj_max      = 76;
1045*0f336e9cSThomas Zimmermann 		param->dll2_finetune_step = 3;
1046*0f336e9cSThomas Zimmermann 		break;
1047*0f336e9cSThomas Zimmermann 	}
1048*0f336e9cSThomas Zimmermann 
1049*0f336e9cSThomas Zimmermann 	switch (param->dram_chipid) {
1050*0f336e9cSThomas Zimmermann 	case AST_DRAM_512Mx16:
1051*0f336e9cSThomas Zimmermann 		param->dram_config = 0x100;
1052*0f336e9cSThomas Zimmermann 		break;
1053*0f336e9cSThomas Zimmermann 	default:
1054*0f336e9cSThomas Zimmermann 	case AST_DRAM_1Gx16:
1055*0f336e9cSThomas Zimmermann 		param->dram_config = 0x121;
1056*0f336e9cSThomas Zimmermann 		break;
1057*0f336e9cSThomas Zimmermann 	case AST_DRAM_2Gx16:
1058*0f336e9cSThomas Zimmermann 		param->dram_config = 0x122;
1059*0f336e9cSThomas Zimmermann 		break;
1060*0f336e9cSThomas Zimmermann 	case AST_DRAM_4Gx16:
1061*0f336e9cSThomas Zimmermann 		param->dram_config = 0x123;
1062*0f336e9cSThomas Zimmermann 		break;
1063*0f336e9cSThomas Zimmermann 	} /* switch size */
1064*0f336e9cSThomas Zimmermann 
1065*0f336e9cSThomas Zimmermann 	switch (param->vram_size) {
1066*0f336e9cSThomas Zimmermann 	default:
1067*0f336e9cSThomas Zimmermann 	case SZ_8M:
1068*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x00;
1069*0f336e9cSThomas Zimmermann 		break;
1070*0f336e9cSThomas Zimmermann 	case SZ_16M:
1071*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x04;
1072*0f336e9cSThomas Zimmermann 		break;
1073*0f336e9cSThomas Zimmermann 	case SZ_32M:
1074*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x08;
1075*0f336e9cSThomas Zimmermann 		break;
1076*0f336e9cSThomas Zimmermann 	case SZ_64M:
1077*0f336e9cSThomas Zimmermann 		param->dram_config |= 0x0c;
1078*0f336e9cSThomas Zimmermann 		break;
1079*0f336e9cSThomas Zimmermann 	}
1080*0f336e9cSThomas Zimmermann }
1081*0f336e9cSThomas Zimmermann 
1082*0f336e9cSThomas Zimmermann static void ddr2_init(struct ast_device *ast, struct ast2300_dram_param *param)
1083*0f336e9cSThomas Zimmermann {
1084*0f336e9cSThomas Zimmermann 	u32 data, data2, retry = 0;
1085*0f336e9cSThomas Zimmermann 
1086*0f336e9cSThomas Zimmermann ddr2_init_start:
1087*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
1088*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
1089*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
1090*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
1091*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1092*0f336e9cSThomas Zimmermann 	udelay(10);
1093*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1094*0f336e9cSThomas Zimmermann 	udelay(10);
1095*0f336e9cSThomas Zimmermann 
1096*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
1097*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
1098*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
1099*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
1100*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
1101*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
1102*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
1103*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
1104*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
1105*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
1106*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
1107*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
1108*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
1109*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
1110*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
1111*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1112*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1113*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0054, 0);
1114*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
1115*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
1116*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1117*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
1118*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
1119*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1120*0f336e9cSThomas Zimmermann 
1121*0f336e9cSThomas Zimmermann 	/* Wait MCLK2X lock to MCLK */
1122*0f336e9cSThomas Zimmermann 	do {
1123*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E001C);
1124*0f336e9cSThomas Zimmermann 	} while (!(data & 0x08000000));
1125*0f336e9cSThomas Zimmermann 	data = ast_mindwm(ast, 0x1E6E001C);
1126*0f336e9cSThomas Zimmermann 	data = (data >> 8) & 0xff;
1127*0f336e9cSThomas Zimmermann 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
1128*0f336e9cSThomas Zimmermann 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1129*0f336e9cSThomas Zimmermann 		if ((data2 & 0xff) > param->madj_max)
1130*0f336e9cSThomas Zimmermann 			break;
1131*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0064, data2);
1132*0f336e9cSThomas Zimmermann 		if (data2 & 0x00100000)
1133*0f336e9cSThomas Zimmermann 			data2 = ((data2 & 0xff) >> 3) + 3;
1134*0f336e9cSThomas Zimmermann 		else
1135*0f336e9cSThomas Zimmermann 			data2 = ((data2 & 0xff) >> 2) + 5;
1136*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1137*0f336e9cSThomas Zimmermann 		data2 += data & 0xff;
1138*0f336e9cSThomas Zimmermann 		data = data | (data2 << 8);
1139*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0068, data);
1140*0f336e9cSThomas Zimmermann 		udelay(10);
1141*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1142*0f336e9cSThomas Zimmermann 		udelay(10);
1143*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
1144*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0018, data);
1145*0f336e9cSThomas Zimmermann 		data = data | 0x200;
1146*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1E6E0018, data);
1147*0f336e9cSThomas Zimmermann 		do {
1148*0f336e9cSThomas Zimmermann 			data = ast_mindwm(ast, 0x1E6E001C);
1149*0f336e9cSThomas Zimmermann 		} while (!(data & 0x08000000));
1150*0f336e9cSThomas Zimmermann 
1151*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E001C);
1152*0f336e9cSThomas Zimmermann 		data = (data >> 8) & 0xff;
1153*0f336e9cSThomas Zimmermann 	}
1154*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
1155*0f336e9cSThomas Zimmermann 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
1156*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0018, data);
1157*0f336e9cSThomas Zimmermann 
1158*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
1159*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1160*0f336e9cSThomas Zimmermann 	udelay(50);
1161*0f336e9cSThomas Zimmermann 	/* Mode Register Setting */
1162*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
1163*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
1164*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
1165*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
1166*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1167*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1168*0f336e9cSThomas Zimmermann 
1169*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
1170*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
1171*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1172*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
1173*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1174*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
1175*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1176*0f336e9cSThomas Zimmermann 
1177*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
1178*0f336e9cSThomas Zimmermann 	data = 0;
1179*0f336e9cSThomas Zimmermann 	if (param->wodt)
1180*0f336e9cSThomas Zimmermann 		data = 0x500;
1181*0f336e9cSThomas Zimmermann 	if (param->rodt)
1182*0f336e9cSThomas Zimmermann 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1183*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
1184*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1185*0f336e9cSThomas Zimmermann 
1186*0f336e9cSThomas Zimmermann 	/* Calibrate the DQSI delay */
1187*0f336e9cSThomas Zimmermann 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1188*0f336e9cSThomas Zimmermann 		goto ddr2_init_start;
1189*0f336e9cSThomas Zimmermann 
1190*0f336e9cSThomas Zimmermann 	/* ECC Memory Initialization */
1191*0f336e9cSThomas Zimmermann #ifdef ECC
1192*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1193*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1194*0f336e9cSThomas Zimmermann 	do {
1195*0f336e9cSThomas Zimmermann 		data = ast_mindwm(ast, 0x1E6E0070);
1196*0f336e9cSThomas Zimmermann 	} while (!(data & 0x00001000));
1197*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1198*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1199*0f336e9cSThomas Zimmermann 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1200*0f336e9cSThomas Zimmermann #endif
1201*0f336e9cSThomas Zimmermann }
1202*0f336e9cSThomas Zimmermann 
1203*0f336e9cSThomas Zimmermann static void ast_post_chip_2300(struct ast_device *ast)
1204*0f336e9cSThomas Zimmermann {
1205*0f336e9cSThomas Zimmermann 	struct ast2300_dram_param param;
1206*0f336e9cSThomas Zimmermann 	u32 temp;
1207*0f336e9cSThomas Zimmermann 	u8 reg;
1208*0f336e9cSThomas Zimmermann 
1209*0f336e9cSThomas Zimmermann 	reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
1210*0f336e9cSThomas Zimmermann 	if ((reg & 0x80) == 0) {/* vga only */
1211*0f336e9cSThomas Zimmermann 		ast_write32(ast, 0xf004, 0x1e6e0000);
1212*0f336e9cSThomas Zimmermann 		ast_write32(ast, 0xf000, 0x1);
1213*0f336e9cSThomas Zimmermann 		ast_write32(ast, 0x12000, 0x1688a8a8);
1214*0f336e9cSThomas Zimmermann 		do {
1215*0f336e9cSThomas Zimmermann 			;
1216*0f336e9cSThomas Zimmermann 		} while (ast_read32(ast, 0x12000) != 0x1);
1217*0f336e9cSThomas Zimmermann 
1218*0f336e9cSThomas Zimmermann 		ast_write32(ast, 0x10000, 0xfc600309);
1219*0f336e9cSThomas Zimmermann 		do {
1220*0f336e9cSThomas Zimmermann 			;
1221*0f336e9cSThomas Zimmermann 		} while (ast_read32(ast, 0x10000) != 0x1);
1222*0f336e9cSThomas Zimmermann 
1223*0f336e9cSThomas Zimmermann 		/* Slow down CPU/AHB CLK in VGA only mode */
1224*0f336e9cSThomas Zimmermann 		temp = ast_read32(ast, 0x12008);
1225*0f336e9cSThomas Zimmermann 		temp |= 0x73;
1226*0f336e9cSThomas Zimmermann 		ast_write32(ast, 0x12008, temp);
1227*0f336e9cSThomas Zimmermann 
1228*0f336e9cSThomas Zimmermann 		param.dram_freq = 396;
1229*0f336e9cSThomas Zimmermann 		param.dram_type = AST_DDR3;
1230*0f336e9cSThomas Zimmermann 		temp = ast_mindwm(ast, 0x1e6e2070);
1231*0f336e9cSThomas Zimmermann 		if (temp & 0x01000000)
1232*0f336e9cSThomas Zimmermann 			param.dram_type = AST_DDR2;
1233*0f336e9cSThomas Zimmermann 		switch (temp & 0x18000000) {
1234*0f336e9cSThomas Zimmermann 		case 0:
1235*0f336e9cSThomas Zimmermann 			param.dram_chipid = AST_DRAM_512Mx16;
1236*0f336e9cSThomas Zimmermann 			break;
1237*0f336e9cSThomas Zimmermann 		default:
1238*0f336e9cSThomas Zimmermann 		case 0x08000000:
1239*0f336e9cSThomas Zimmermann 			param.dram_chipid = AST_DRAM_1Gx16;
1240*0f336e9cSThomas Zimmermann 			break;
1241*0f336e9cSThomas Zimmermann 		case 0x10000000:
1242*0f336e9cSThomas Zimmermann 			param.dram_chipid = AST_DRAM_2Gx16;
1243*0f336e9cSThomas Zimmermann 			break;
1244*0f336e9cSThomas Zimmermann 		case 0x18000000:
1245*0f336e9cSThomas Zimmermann 			param.dram_chipid = AST_DRAM_4Gx16;
1246*0f336e9cSThomas Zimmermann 			break;
1247*0f336e9cSThomas Zimmermann 		}
1248*0f336e9cSThomas Zimmermann 		switch (temp & 0x0c) {
1249*0f336e9cSThomas Zimmermann 		default:
1250*0f336e9cSThomas Zimmermann 		case 0x00:
1251*0f336e9cSThomas Zimmermann 			param.vram_size = SZ_8M;
1252*0f336e9cSThomas Zimmermann 			break;
1253*0f336e9cSThomas Zimmermann 		case 0x04:
1254*0f336e9cSThomas Zimmermann 			param.vram_size = SZ_16M;
1255*0f336e9cSThomas Zimmermann 			break;
1256*0f336e9cSThomas Zimmermann 		case 0x08:
1257*0f336e9cSThomas Zimmermann 			param.vram_size = SZ_32M;
1258*0f336e9cSThomas Zimmermann 			break;
1259*0f336e9cSThomas Zimmermann 		case 0x0c:
1260*0f336e9cSThomas Zimmermann 			param.vram_size = SZ_64M;
1261*0f336e9cSThomas Zimmermann 			break;
1262*0f336e9cSThomas Zimmermann 		}
1263*0f336e9cSThomas Zimmermann 
1264*0f336e9cSThomas Zimmermann 		if (param.dram_type == AST_DDR3) {
1265*0f336e9cSThomas Zimmermann 			get_ddr3_info(ast, &param);
1266*0f336e9cSThomas Zimmermann 			ddr3_init(ast, &param);
1267*0f336e9cSThomas Zimmermann 		} else {
1268*0f336e9cSThomas Zimmermann 			get_ddr2_info(ast, &param);
1269*0f336e9cSThomas Zimmermann 			ddr2_init(ast, &param);
1270*0f336e9cSThomas Zimmermann 		}
1271*0f336e9cSThomas Zimmermann 
1272*0f336e9cSThomas Zimmermann 		temp = ast_mindwm(ast, 0x1e6e2040);
1273*0f336e9cSThomas Zimmermann 		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
1274*0f336e9cSThomas Zimmermann 	}
1275*0f336e9cSThomas Zimmermann 
1276*0f336e9cSThomas Zimmermann 	/* wait ready */
1277*0f336e9cSThomas Zimmermann 	do {
1278*0f336e9cSThomas Zimmermann 		reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
1279*0f336e9cSThomas Zimmermann 	} while ((reg & 0x40) == 0);
1280*0f336e9cSThomas Zimmermann }
1281*0f336e9cSThomas Zimmermann 
1282*0f336e9cSThomas Zimmermann int ast_2300_post(struct ast_device *ast)
1283*0f336e9cSThomas Zimmermann {
1284*0f336e9cSThomas Zimmermann 	if (ast->config_mode == ast_use_p2a) {
1285*0f336e9cSThomas Zimmermann 		ast_post_chip_2300(ast);
1286*0f336e9cSThomas Zimmermann 		ast_init_3rdtx(ast);
1287*0f336e9cSThomas Zimmermann 	} else {
1288*0f336e9cSThomas Zimmermann 		if (ast->tx_chip == AST_TX_SIL164) {
1289*0f336e9cSThomas Zimmermann 			/* Enable DVO */
1290*0f336e9cSThomas Zimmermann 			ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80);
1291*0f336e9cSThomas Zimmermann 		}
1292*0f336e9cSThomas Zimmermann 	}
1293*0f336e9cSThomas Zimmermann 
1294*0f336e9cSThomas Zimmermann 	return 0;
1295*0f336e9cSThomas Zimmermann }
1296