xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/ast/ast_post.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2012 Red Hat Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the
6*4882a593Smuzhiyun  * "Software"), to deal in the Software without restriction, including
7*4882a593Smuzhiyun  * without limitation the rights to use, copy, modify, merge, publish,
8*4882a593Smuzhiyun  * distribute, sub license, and/or sell copies of the Software, and to
9*4882a593Smuzhiyun  * permit persons to whom the Software is furnished to do so, subject to
10*4882a593Smuzhiyun  * the following conditions:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15*4882a593Smuzhiyun  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16*4882a593Smuzhiyun  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17*4882a593Smuzhiyun  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18*4882a593Smuzhiyun  * USE OR OTHER DEALINGS IN THE SOFTWARE.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the
21*4882a593Smuzhiyun  * next paragraph) shall be included in all copies or substantial portions
22*4882a593Smuzhiyun  * of the Software.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun /*
26*4882a593Smuzhiyun  * Authors: Dave Airlie <airlied@redhat.com>
27*4882a593Smuzhiyun  */
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <linux/delay.h>
30*4882a593Smuzhiyun #include <linux/pci.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include <drm/drm_print.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "ast_dram_tables.h"
35*4882a593Smuzhiyun #include "ast_drv.h"
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun static void ast_post_chip_2300(struct drm_device *dev);
38*4882a593Smuzhiyun static void ast_post_chip_2500(struct drm_device *dev);
39*4882a593Smuzhiyun 
ast_enable_vga(struct drm_device * dev)40*4882a593Smuzhiyun void ast_enable_vga(struct drm_device *dev)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01);
45*4882a593Smuzhiyun 	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01);
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
ast_enable_mmio(struct drm_device * dev)48*4882a593Smuzhiyun void ast_enable_mmio(struct drm_device *dev)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 
ast_is_vga_enabled(struct drm_device * dev)56*4882a593Smuzhiyun bool ast_is_vga_enabled(struct drm_device *dev)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
59*4882a593Smuzhiyun 	u8 ch;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	return !!(ch & 0x01);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
67*4882a593Smuzhiyun static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff };
68*4882a593Smuzhiyun static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff };
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static void
ast_set_def_ext_reg(struct drm_device * dev)71*4882a593Smuzhiyun ast_set_def_ext_reg(struct drm_device *dev)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
74*4882a593Smuzhiyun 	u8 i, index, reg;
75*4882a593Smuzhiyun 	const u8 *ext_reg_info;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	/* reset scratch */
78*4882a593Smuzhiyun 	for (i = 0x81; i <= 0x9f; i++)
79*4882a593Smuzhiyun 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (ast->chip == AST2300 || ast->chip == AST2400 ||
82*4882a593Smuzhiyun 	    ast->chip == AST2500) {
83*4882a593Smuzhiyun 		if (dev->pdev->revision >= 0x20)
84*4882a593Smuzhiyun 			ext_reg_info = extreginfo_ast2300;
85*4882a593Smuzhiyun 		else
86*4882a593Smuzhiyun 			ext_reg_info = extreginfo_ast2300a0;
87*4882a593Smuzhiyun 	} else
88*4882a593Smuzhiyun 		ext_reg_info = extreginfo;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	index = 0xa0;
91*4882a593Smuzhiyun 	while (*ext_reg_info != 0xff) {
92*4882a593Smuzhiyun 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info);
93*4882a593Smuzhiyun 		index++;
94*4882a593Smuzhiyun 		ext_reg_info++;
95*4882a593Smuzhiyun 	}
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	/* disable standard IO/MEM decode if secondary */
98*4882a593Smuzhiyun 	/* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	/* Set Ext. Default */
101*4882a593Smuzhiyun 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01);
102*4882a593Smuzhiyun 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	/* Enable RAMDAC for A1 */
105*4882a593Smuzhiyun 	reg = 0x04;
106*4882a593Smuzhiyun 	if (ast->chip == AST2300 || ast->chip == AST2400 ||
107*4882a593Smuzhiyun 	    ast->chip == AST2500)
108*4882a593Smuzhiyun 		reg |= 0x20;
109*4882a593Smuzhiyun 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
ast_mindwm(struct ast_private * ast,u32 r)112*4882a593Smuzhiyun u32 ast_mindwm(struct ast_private *ast, u32 r)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	uint32_t data;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	ast_write32(ast, 0xf004, r & 0xffff0000);
117*4882a593Smuzhiyun 	ast_write32(ast, 0xf000, 0x1);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	do {
120*4882a593Smuzhiyun 		data = ast_read32(ast, 0xf004) & 0xffff0000;
121*4882a593Smuzhiyun 	} while (data != (r & 0xffff0000));
122*4882a593Smuzhiyun 	return ast_read32(ast, 0x10000 + (r & 0x0000ffff));
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
ast_moutdwm(struct ast_private * ast,u32 r,u32 v)125*4882a593Smuzhiyun void ast_moutdwm(struct ast_private *ast, u32 r, u32 v)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	uint32_t data;
128*4882a593Smuzhiyun 	ast_write32(ast, 0xf004, r & 0xffff0000);
129*4882a593Smuzhiyun 	ast_write32(ast, 0xf000, 0x1);
130*4882a593Smuzhiyun 	do {
131*4882a593Smuzhiyun 		data = ast_read32(ast, 0xf004) & 0xffff0000;
132*4882a593Smuzhiyun 	} while (data != (r & 0xffff0000));
133*4882a593Smuzhiyun 	ast_write32(ast, 0x10000 + (r & 0x0000ffff), v);
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun  * AST2100/2150 DLL CBR Setting
138*4882a593Smuzhiyun  */
139*4882a593Smuzhiyun #define CBR_SIZE_AST2150	     ((16 << 10) - 1)
140*4882a593Smuzhiyun #define CBR_PASSNUM_AST2150          5
141*4882a593Smuzhiyun #define CBR_THRESHOLD_AST2150        10
142*4882a593Smuzhiyun #define CBR_THRESHOLD2_AST2150       10
143*4882a593Smuzhiyun #define TIMEOUT_AST2150              5000000
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun #define CBR_PATNUM_AST2150           8
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun static const u32 pattern_AST2150[14] = {
148*4882a593Smuzhiyun 	0xFF00FF00,
149*4882a593Smuzhiyun 	0xCC33CC33,
150*4882a593Smuzhiyun 	0xAA55AA55,
151*4882a593Smuzhiyun 	0xFFFE0001,
152*4882a593Smuzhiyun 	0x683501FE,
153*4882a593Smuzhiyun 	0x0F1929B0,
154*4882a593Smuzhiyun 	0x2D0B4346,
155*4882a593Smuzhiyun 	0x60767F02,
156*4882a593Smuzhiyun 	0x6FBE36A6,
157*4882a593Smuzhiyun 	0x3A253035,
158*4882a593Smuzhiyun 	0x3019686D,
159*4882a593Smuzhiyun 	0x41C6167E,
160*4882a593Smuzhiyun 	0x620152BF,
161*4882a593Smuzhiyun 	0x20F050E0
162*4882a593Smuzhiyun };
163*4882a593Smuzhiyun 
mmctestburst2_ast2150(struct ast_private * ast,u32 datagen)164*4882a593Smuzhiyun static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	u32 data, timeout;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
169*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3));
170*4882a593Smuzhiyun 	timeout = 0;
171*4882a593Smuzhiyun 	do {
172*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
173*4882a593Smuzhiyun 		if (++timeout > TIMEOUT_AST2150) {
174*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
175*4882a593Smuzhiyun 			return 0xffffffff;
176*4882a593Smuzhiyun 		}
177*4882a593Smuzhiyun 	} while (!data);
178*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
179*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3));
180*4882a593Smuzhiyun 	timeout = 0;
181*4882a593Smuzhiyun 	do {
182*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
183*4882a593Smuzhiyun 		if (++timeout > TIMEOUT_AST2150) {
184*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
185*4882a593Smuzhiyun 			return 0xffffffff;
186*4882a593Smuzhiyun 		}
187*4882a593Smuzhiyun 	} while (!data);
188*4882a593Smuzhiyun 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
189*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
190*4882a593Smuzhiyun 	return data;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun #if 0 /* unused in DDX driver - here for completeness */
194*4882a593Smuzhiyun static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	u32 data, timeout;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
199*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
200*4882a593Smuzhiyun 	timeout = 0;
201*4882a593Smuzhiyun 	do {
202*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
203*4882a593Smuzhiyun 		if (++timeout > TIMEOUT_AST2150) {
204*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
205*4882a593Smuzhiyun 			return 0xffffffff;
206*4882a593Smuzhiyun 		}
207*4882a593Smuzhiyun 	} while (!data);
208*4882a593Smuzhiyun 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
209*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
210*4882a593Smuzhiyun 	return data;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun #endif
213*4882a593Smuzhiyun 
cbrtest_ast2150(struct ast_private * ast)214*4882a593Smuzhiyun static int cbrtest_ast2150(struct ast_private *ast)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	int i;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	for (i = 0; i < 8; i++)
219*4882a593Smuzhiyun 		if (mmctestburst2_ast2150(ast, i))
220*4882a593Smuzhiyun 			return 0;
221*4882a593Smuzhiyun 	return 1;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun 
cbrscan_ast2150(struct ast_private * ast,int busw)224*4882a593Smuzhiyun static int cbrscan_ast2150(struct ast_private *ast, int busw)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	u32 patcnt, loop;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) {
229*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]);
230*4882a593Smuzhiyun 		for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) {
231*4882a593Smuzhiyun 			if (cbrtest_ast2150(ast))
232*4882a593Smuzhiyun 				break;
233*4882a593Smuzhiyun 		}
234*4882a593Smuzhiyun 		if (loop == CBR_PASSNUM_AST2150)
235*4882a593Smuzhiyun 			return 0;
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 	return 1;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 
cbrdlli_ast2150(struct ast_private * ast,int busw)241*4882a593Smuzhiyun static void cbrdlli_ast2150(struct ast_private *ast, int busw)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	u32 dll_min[4], dll_max[4], dlli, data, passcnt;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun cbr_start:
246*4882a593Smuzhiyun 	dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff;
247*4882a593Smuzhiyun 	dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0;
248*4882a593Smuzhiyun 	passcnt = 0;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	for (dlli = 0; dlli < 100; dlli++) {
251*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
252*4882a593Smuzhiyun 		data = cbrscan_ast2150(ast, busw);
253*4882a593Smuzhiyun 		if (data != 0) {
254*4882a593Smuzhiyun 			if (data & 0x1) {
255*4882a593Smuzhiyun 				if (dll_min[0] > dlli)
256*4882a593Smuzhiyun 					dll_min[0] = dlli;
257*4882a593Smuzhiyun 				if (dll_max[0] < dlli)
258*4882a593Smuzhiyun 					dll_max[0] = dlli;
259*4882a593Smuzhiyun 			}
260*4882a593Smuzhiyun 			passcnt++;
261*4882a593Smuzhiyun 		} else if (passcnt >= CBR_THRESHOLD_AST2150)
262*4882a593Smuzhiyun 			goto cbr_start;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 	if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150)
265*4882a593Smuzhiyun 		goto cbr_start;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4);
268*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 
ast_init_dram_reg(struct drm_device * dev)273*4882a593Smuzhiyun static void ast_init_dram_reg(struct drm_device *dev)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
276*4882a593Smuzhiyun 	u8 j;
277*4882a593Smuzhiyun 	u32 data, temp, i;
278*4882a593Smuzhiyun 	const struct ast_dramstruct *dram_reg_info;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	if ((j & 0x80) == 0) { /* VGA only */
283*4882a593Smuzhiyun 		if (ast->chip == AST2000) {
284*4882a593Smuzhiyun 			dram_reg_info = ast2000_dram_table_data;
285*4882a593Smuzhiyun 			ast_write32(ast, 0xf004, 0x1e6e0000);
286*4882a593Smuzhiyun 			ast_write32(ast, 0xf000, 0x1);
287*4882a593Smuzhiyun 			ast_write32(ast, 0x10100, 0xa8);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 			do {
290*4882a593Smuzhiyun 				;
291*4882a593Smuzhiyun 			} while (ast_read32(ast, 0x10100) != 0xa8);
292*4882a593Smuzhiyun 		} else {/* AST2100/1100 */
293*4882a593Smuzhiyun 			if (ast->chip == AST2100 || ast->chip == 2200)
294*4882a593Smuzhiyun 				dram_reg_info = ast2100_dram_table_data;
295*4882a593Smuzhiyun 			else
296*4882a593Smuzhiyun 				dram_reg_info = ast1100_dram_table_data;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 			ast_write32(ast, 0xf004, 0x1e6e0000);
299*4882a593Smuzhiyun 			ast_write32(ast, 0xf000, 0x1);
300*4882a593Smuzhiyun 			ast_write32(ast, 0x12000, 0x1688A8A8);
301*4882a593Smuzhiyun 			do {
302*4882a593Smuzhiyun 				;
303*4882a593Smuzhiyun 			} while (ast_read32(ast, 0x12000) != 0x01);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 			ast_write32(ast, 0x10000, 0xfc600309);
306*4882a593Smuzhiyun 			do {
307*4882a593Smuzhiyun 				;
308*4882a593Smuzhiyun 			} while (ast_read32(ast, 0x10000) != 0x01);
309*4882a593Smuzhiyun 		}
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 		while (dram_reg_info->index != 0xffff) {
312*4882a593Smuzhiyun 			if (dram_reg_info->index == 0xff00) {/* delay fn */
313*4882a593Smuzhiyun 				for (i = 0; i < 15; i++)
314*4882a593Smuzhiyun 					udelay(dram_reg_info->data);
315*4882a593Smuzhiyun 			} else if (dram_reg_info->index == 0x4 && ast->chip != AST2000) {
316*4882a593Smuzhiyun 				data = dram_reg_info->data;
317*4882a593Smuzhiyun 				if (ast->dram_type == AST_DRAM_1Gx16)
318*4882a593Smuzhiyun 					data = 0x00000d89;
319*4882a593Smuzhiyun 				else if (ast->dram_type == AST_DRAM_1Gx32)
320*4882a593Smuzhiyun 					data = 0x00000c8d;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 				temp = ast_read32(ast, 0x12070);
323*4882a593Smuzhiyun 				temp &= 0xc;
324*4882a593Smuzhiyun 				temp <<= 2;
325*4882a593Smuzhiyun 				ast_write32(ast, 0x10000 + dram_reg_info->index, data | temp);
326*4882a593Smuzhiyun 			} else
327*4882a593Smuzhiyun 				ast_write32(ast, 0x10000 + dram_reg_info->index, dram_reg_info->data);
328*4882a593Smuzhiyun 			dram_reg_info++;
329*4882a593Smuzhiyun 		}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 		/* AST 2100/2150 DRAM calibration */
332*4882a593Smuzhiyun 		data = ast_read32(ast, 0x10120);
333*4882a593Smuzhiyun 		if (data == 0x5061) { /* 266Mhz */
334*4882a593Smuzhiyun 			data = ast_read32(ast, 0x10004);
335*4882a593Smuzhiyun 			if (data & 0x40)
336*4882a593Smuzhiyun 				cbrdlli_ast2150(ast, 16); /* 16 bits */
337*4882a593Smuzhiyun 			else
338*4882a593Smuzhiyun 				cbrdlli_ast2150(ast, 32); /* 32 bits */
339*4882a593Smuzhiyun 		}
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 		switch (ast->chip) {
342*4882a593Smuzhiyun 		case AST2000:
343*4882a593Smuzhiyun 			temp = ast_read32(ast, 0x10140);
344*4882a593Smuzhiyun 			ast_write32(ast, 0x10140, temp | 0x40);
345*4882a593Smuzhiyun 			break;
346*4882a593Smuzhiyun 		case AST1100:
347*4882a593Smuzhiyun 		case AST2100:
348*4882a593Smuzhiyun 		case AST2200:
349*4882a593Smuzhiyun 		case AST2150:
350*4882a593Smuzhiyun 			temp = ast_read32(ast, 0x1200c);
351*4882a593Smuzhiyun 			ast_write32(ast, 0x1200c, temp & 0xfffffffd);
352*4882a593Smuzhiyun 			temp = ast_read32(ast, 0x12040);
353*4882a593Smuzhiyun 			ast_write32(ast, 0x12040, temp | 0x40);
354*4882a593Smuzhiyun 			break;
355*4882a593Smuzhiyun 		default:
356*4882a593Smuzhiyun 			break;
357*4882a593Smuzhiyun 		}
358*4882a593Smuzhiyun 	}
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	/* wait ready */
361*4882a593Smuzhiyun 	do {
362*4882a593Smuzhiyun 		j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
363*4882a593Smuzhiyun 	} while ((j & 0x40) == 0);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun 
ast_post_gpu(struct drm_device * dev)366*4882a593Smuzhiyun void ast_post_gpu(struct drm_device *dev)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
369*4882a593Smuzhiyun 	u32 reg;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	pci_read_config_dword(dev->pdev, 0x04, &reg);
372*4882a593Smuzhiyun 	reg |= 0x3;
373*4882a593Smuzhiyun 	pci_write_config_dword(dev->pdev, 0x04, reg);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	ast_enable_vga(dev);
376*4882a593Smuzhiyun 	ast_open_key(ast);
377*4882a593Smuzhiyun 	ast_enable_mmio(dev);
378*4882a593Smuzhiyun 	ast_set_def_ext_reg(dev);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (ast->config_mode == ast_use_p2a) {
381*4882a593Smuzhiyun 		if (ast->chip == AST2500)
382*4882a593Smuzhiyun 			ast_post_chip_2500(dev);
383*4882a593Smuzhiyun 		else if (ast->chip == AST2300 || ast->chip == AST2400)
384*4882a593Smuzhiyun 			ast_post_chip_2300(dev);
385*4882a593Smuzhiyun 		else
386*4882a593Smuzhiyun 			ast_init_dram_reg(dev);
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 		ast_init_3rdtx(dev);
389*4882a593Smuzhiyun 	} else {
390*4882a593Smuzhiyun 		if (ast->tx_chip_type != AST_TX_NONE)
391*4882a593Smuzhiyun 			ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);	/* Enable DVO */
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun /* AST 2300 DRAM settings */
396*4882a593Smuzhiyun #define AST_DDR3 0
397*4882a593Smuzhiyun #define AST_DDR2 1
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun struct ast2300_dram_param {
400*4882a593Smuzhiyun 	u32 dram_type;
401*4882a593Smuzhiyun 	u32 dram_chipid;
402*4882a593Smuzhiyun 	u32 dram_freq;
403*4882a593Smuzhiyun 	u32 vram_size;
404*4882a593Smuzhiyun 	u32 odt;
405*4882a593Smuzhiyun 	u32 wodt;
406*4882a593Smuzhiyun 	u32 rodt;
407*4882a593Smuzhiyun 	u32 dram_config;
408*4882a593Smuzhiyun 	u32 reg_PERIOD;
409*4882a593Smuzhiyun 	u32 reg_MADJ;
410*4882a593Smuzhiyun 	u32 reg_SADJ;
411*4882a593Smuzhiyun 	u32 reg_MRS;
412*4882a593Smuzhiyun 	u32 reg_EMRS;
413*4882a593Smuzhiyun 	u32 reg_AC1;
414*4882a593Smuzhiyun 	u32 reg_AC2;
415*4882a593Smuzhiyun 	u32 reg_DQSIC;
416*4882a593Smuzhiyun 	u32 reg_DRV;
417*4882a593Smuzhiyun 	u32 reg_IOZ;
418*4882a593Smuzhiyun 	u32 reg_DQIDLY;
419*4882a593Smuzhiyun 	u32 reg_FREQ;
420*4882a593Smuzhiyun 	u32 madj_max;
421*4882a593Smuzhiyun 	u32 dll2_finetune_step;
422*4882a593Smuzhiyun };
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun /*
425*4882a593Smuzhiyun  * DQSI DLL CBR Setting
426*4882a593Smuzhiyun  */
427*4882a593Smuzhiyun #define CBR_SIZE0            ((1  << 10) - 1)
428*4882a593Smuzhiyun #define CBR_SIZE1            ((4  << 10) - 1)
429*4882a593Smuzhiyun #define CBR_SIZE2            ((64 << 10) - 1)
430*4882a593Smuzhiyun #define CBR_PASSNUM          5
431*4882a593Smuzhiyun #define CBR_PASSNUM2         5
432*4882a593Smuzhiyun #define CBR_THRESHOLD        10
433*4882a593Smuzhiyun #define CBR_THRESHOLD2       10
434*4882a593Smuzhiyun #define TIMEOUT              5000000
435*4882a593Smuzhiyun #define CBR_PATNUM           8
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun static const u32 pattern[8] = {
438*4882a593Smuzhiyun 	0xFF00FF00,
439*4882a593Smuzhiyun 	0xCC33CC33,
440*4882a593Smuzhiyun 	0xAA55AA55,
441*4882a593Smuzhiyun 	0x88778877,
442*4882a593Smuzhiyun 	0x92CC4D6E,
443*4882a593Smuzhiyun 	0x543D3CDE,
444*4882a593Smuzhiyun 	0xF1E843C7,
445*4882a593Smuzhiyun 	0x7C61D253
446*4882a593Smuzhiyun };
447*4882a593Smuzhiyun 
mmc_test(struct ast_private * ast,u32 datagen,u8 test_ctl)448*4882a593Smuzhiyun static bool mmc_test(struct ast_private *ast, u32 datagen, u8 test_ctl)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun 	u32 data, timeout;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
453*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
454*4882a593Smuzhiyun 	timeout = 0;
455*4882a593Smuzhiyun 	do {
456*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
457*4882a593Smuzhiyun 		if (data & 0x2000)
458*4882a593Smuzhiyun 			return false;
459*4882a593Smuzhiyun 		if (++timeout > TIMEOUT) {
460*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
461*4882a593Smuzhiyun 			return false;
462*4882a593Smuzhiyun 		}
463*4882a593Smuzhiyun 	} while (!data);
464*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
465*4882a593Smuzhiyun 	return true;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
mmc_test2(struct ast_private * ast,u32 datagen,u8 test_ctl)468*4882a593Smuzhiyun static u32 mmc_test2(struct ast_private *ast, u32 datagen, u8 test_ctl)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	u32 data, timeout;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
473*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
474*4882a593Smuzhiyun 	timeout = 0;
475*4882a593Smuzhiyun 	do {
476*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
477*4882a593Smuzhiyun 		if (++timeout > TIMEOUT) {
478*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
479*4882a593Smuzhiyun 			return 0xffffffff;
480*4882a593Smuzhiyun 		}
481*4882a593Smuzhiyun 	} while (!data);
482*4882a593Smuzhiyun 	data = ast_mindwm(ast, 0x1e6e0078);
483*4882a593Smuzhiyun 	data = (data | (data >> 16)) & 0xffff;
484*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
485*4882a593Smuzhiyun 	return data;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 
mmc_test_burst(struct ast_private * ast,u32 datagen)489*4882a593Smuzhiyun static bool mmc_test_burst(struct ast_private *ast, u32 datagen)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun 	return mmc_test(ast, datagen, 0xc1);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun 
mmc_test_burst2(struct ast_private * ast,u32 datagen)494*4882a593Smuzhiyun static u32 mmc_test_burst2(struct ast_private *ast, u32 datagen)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun 	return mmc_test2(ast, datagen, 0x41);
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun 
mmc_test_single(struct ast_private * ast,u32 datagen)499*4882a593Smuzhiyun static bool mmc_test_single(struct ast_private *ast, u32 datagen)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun 	return mmc_test(ast, datagen, 0xc5);
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
mmc_test_single2(struct ast_private * ast,u32 datagen)504*4882a593Smuzhiyun static u32 mmc_test_single2(struct ast_private *ast, u32 datagen)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun 	return mmc_test2(ast, datagen, 0x05);
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun 
mmc_test_single_2500(struct ast_private * ast,u32 datagen)509*4882a593Smuzhiyun static bool mmc_test_single_2500(struct ast_private *ast, u32 datagen)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun 	return mmc_test(ast, datagen, 0x85);
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun 
cbr_test(struct ast_private * ast)514*4882a593Smuzhiyun static int cbr_test(struct ast_private *ast)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun 	u32 data;
517*4882a593Smuzhiyun 	int i;
518*4882a593Smuzhiyun 	data = mmc_test_single2(ast, 0);
519*4882a593Smuzhiyun 	if ((data & 0xff) && (data & 0xff00))
520*4882a593Smuzhiyun 		return 0;
521*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
522*4882a593Smuzhiyun 		data = mmc_test_burst2(ast, i);
523*4882a593Smuzhiyun 		if ((data & 0xff) && (data & 0xff00))
524*4882a593Smuzhiyun 			return 0;
525*4882a593Smuzhiyun 	}
526*4882a593Smuzhiyun 	if (!data)
527*4882a593Smuzhiyun 		return 3;
528*4882a593Smuzhiyun 	else if (data & 0xff)
529*4882a593Smuzhiyun 		return 2;
530*4882a593Smuzhiyun 	return 1;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
cbr_scan(struct ast_private * ast)533*4882a593Smuzhiyun static int cbr_scan(struct ast_private *ast)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun 	u32 data, data2, patcnt, loop;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	data2 = 3;
538*4882a593Smuzhiyun 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
539*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
540*4882a593Smuzhiyun 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
541*4882a593Smuzhiyun 			if ((data = cbr_test(ast)) != 0) {
542*4882a593Smuzhiyun 				data2 &= data;
543*4882a593Smuzhiyun 				if (!data2)
544*4882a593Smuzhiyun 					return 0;
545*4882a593Smuzhiyun 				break;
546*4882a593Smuzhiyun 			}
547*4882a593Smuzhiyun 		}
548*4882a593Smuzhiyun 		if (loop == CBR_PASSNUM2)
549*4882a593Smuzhiyun 			return 0;
550*4882a593Smuzhiyun 	}
551*4882a593Smuzhiyun 	return data2;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun 
cbr_test2(struct ast_private * ast)554*4882a593Smuzhiyun static u32 cbr_test2(struct ast_private *ast)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun 	u32 data;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	data = mmc_test_burst2(ast, 0);
559*4882a593Smuzhiyun 	if (data == 0xffff)
560*4882a593Smuzhiyun 		return 0;
561*4882a593Smuzhiyun 	data |= mmc_test_single2(ast, 0);
562*4882a593Smuzhiyun 	if (data == 0xffff)
563*4882a593Smuzhiyun 		return 0;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	return ~data & 0xffff;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
cbr_scan2(struct ast_private * ast)568*4882a593Smuzhiyun static u32 cbr_scan2(struct ast_private *ast)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun 	u32 data, data2, patcnt, loop;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	data2 = 0xffff;
573*4882a593Smuzhiyun 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
574*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
575*4882a593Smuzhiyun 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
576*4882a593Smuzhiyun 			if ((data = cbr_test2(ast)) != 0) {
577*4882a593Smuzhiyun 				data2 &= data;
578*4882a593Smuzhiyun 				if (!data2)
579*4882a593Smuzhiyun 					return 0;
580*4882a593Smuzhiyun 				break;
581*4882a593Smuzhiyun 			}
582*4882a593Smuzhiyun 		}
583*4882a593Smuzhiyun 		if (loop == CBR_PASSNUM2)
584*4882a593Smuzhiyun 			return 0;
585*4882a593Smuzhiyun 	}
586*4882a593Smuzhiyun 	return data2;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun 
cbr_test3(struct ast_private * ast)589*4882a593Smuzhiyun static bool cbr_test3(struct ast_private *ast)
590*4882a593Smuzhiyun {
591*4882a593Smuzhiyun 	if (!mmc_test_burst(ast, 0))
592*4882a593Smuzhiyun 		return false;
593*4882a593Smuzhiyun 	if (!mmc_test_single(ast, 0))
594*4882a593Smuzhiyun 		return false;
595*4882a593Smuzhiyun 	return true;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun 
cbr_scan3(struct ast_private * ast)598*4882a593Smuzhiyun static bool cbr_scan3(struct ast_private *ast)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun 	u32 patcnt, loop;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
603*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
604*4882a593Smuzhiyun 		for (loop = 0; loop < 2; loop++) {
605*4882a593Smuzhiyun 			if (cbr_test3(ast))
606*4882a593Smuzhiyun 				break;
607*4882a593Smuzhiyun 		}
608*4882a593Smuzhiyun 		if (loop == 2)
609*4882a593Smuzhiyun 			return false;
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 	return true;
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun 
finetuneDQI_L(struct ast_private * ast,struct ast2300_dram_param * param)614*4882a593Smuzhiyun static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun 	u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
617*4882a593Smuzhiyun 	bool status = false;
618*4882a593Smuzhiyun FINETUNE_START:
619*4882a593Smuzhiyun 	for (cnt = 0; cnt < 16; cnt++) {
620*4882a593Smuzhiyun 		dllmin[cnt] = 0xff;
621*4882a593Smuzhiyun 		dllmax[cnt] = 0x0;
622*4882a593Smuzhiyun 	}
623*4882a593Smuzhiyun 	passcnt = 0;
624*4882a593Smuzhiyun 	for (dlli = 0; dlli < 76; dlli++) {
625*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24));
626*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
627*4882a593Smuzhiyun 		data = cbr_scan2(ast);
628*4882a593Smuzhiyun 		if (data != 0) {
629*4882a593Smuzhiyun 			mask = 0x00010001;
630*4882a593Smuzhiyun 			for (cnt = 0; cnt < 16; cnt++) {
631*4882a593Smuzhiyun 				if (data & mask) {
632*4882a593Smuzhiyun 					if (dllmin[cnt] > dlli) {
633*4882a593Smuzhiyun 						dllmin[cnt] = dlli;
634*4882a593Smuzhiyun 					}
635*4882a593Smuzhiyun 					if (dllmax[cnt] < dlli) {
636*4882a593Smuzhiyun 						dllmax[cnt] = dlli;
637*4882a593Smuzhiyun 					}
638*4882a593Smuzhiyun 				}
639*4882a593Smuzhiyun 				mask <<= 1;
640*4882a593Smuzhiyun 			}
641*4882a593Smuzhiyun 			passcnt++;
642*4882a593Smuzhiyun 		} else if (passcnt >= CBR_THRESHOLD2) {
643*4882a593Smuzhiyun 			break;
644*4882a593Smuzhiyun 		}
645*4882a593Smuzhiyun 	}
646*4882a593Smuzhiyun 	gold_sadj[0] = 0x0;
647*4882a593Smuzhiyun 	passcnt = 0;
648*4882a593Smuzhiyun 	for (cnt = 0; cnt < 16; cnt++) {
649*4882a593Smuzhiyun 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
650*4882a593Smuzhiyun 			gold_sadj[0] += dllmin[cnt];
651*4882a593Smuzhiyun 			passcnt++;
652*4882a593Smuzhiyun 		}
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun 	if (retry++ > 10)
655*4882a593Smuzhiyun 		goto FINETUNE_DONE;
656*4882a593Smuzhiyun 	if (passcnt != 16) {
657*4882a593Smuzhiyun 		goto FINETUNE_START;
658*4882a593Smuzhiyun 	}
659*4882a593Smuzhiyun 	status = true;
660*4882a593Smuzhiyun FINETUNE_DONE:
661*4882a593Smuzhiyun 	gold_sadj[0] = gold_sadj[0] >> 4;
662*4882a593Smuzhiyun 	gold_sadj[1] = gold_sadj[0];
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	data = 0;
665*4882a593Smuzhiyun 	for (cnt = 0; cnt < 8; cnt++) {
666*4882a593Smuzhiyun 		data >>= 3;
667*4882a593Smuzhiyun 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
668*4882a593Smuzhiyun 			dlli = dllmin[cnt];
669*4882a593Smuzhiyun 			if (gold_sadj[0] >= dlli) {
670*4882a593Smuzhiyun 				dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
671*4882a593Smuzhiyun 				if (dlli > 3) {
672*4882a593Smuzhiyun 					dlli = 3;
673*4882a593Smuzhiyun 				}
674*4882a593Smuzhiyun 			} else {
675*4882a593Smuzhiyun 				dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
676*4882a593Smuzhiyun 				if (dlli > 4) {
677*4882a593Smuzhiyun 					dlli = 4;
678*4882a593Smuzhiyun 				}
679*4882a593Smuzhiyun 				dlli = (8 - dlli) & 0x7;
680*4882a593Smuzhiyun 			}
681*4882a593Smuzhiyun 			data |= dlli << 21;
682*4882a593Smuzhiyun 		}
683*4882a593Smuzhiyun 	}
684*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0080, data);
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	data = 0;
687*4882a593Smuzhiyun 	for (cnt = 8; cnt < 16; cnt++) {
688*4882a593Smuzhiyun 		data >>= 3;
689*4882a593Smuzhiyun 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
690*4882a593Smuzhiyun 			dlli = dllmin[cnt];
691*4882a593Smuzhiyun 			if (gold_sadj[1] >= dlli) {
692*4882a593Smuzhiyun 				dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
693*4882a593Smuzhiyun 				if (dlli > 3) {
694*4882a593Smuzhiyun 					dlli = 3;
695*4882a593Smuzhiyun 				} else {
696*4882a593Smuzhiyun 					dlli = (dlli - 1) & 0x7;
697*4882a593Smuzhiyun 				}
698*4882a593Smuzhiyun 			} else {
699*4882a593Smuzhiyun 				dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
700*4882a593Smuzhiyun 				dlli += 1;
701*4882a593Smuzhiyun 				if (dlli > 4) {
702*4882a593Smuzhiyun 					dlli = 4;
703*4882a593Smuzhiyun 				}
704*4882a593Smuzhiyun 				dlli = (8 - dlli) & 0x7;
705*4882a593Smuzhiyun 			}
706*4882a593Smuzhiyun 			data |= dlli << 21;
707*4882a593Smuzhiyun 		}
708*4882a593Smuzhiyun 	}
709*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0084, data);
710*4882a593Smuzhiyun 	return status;
711*4882a593Smuzhiyun } /* finetuneDQI_L */
712*4882a593Smuzhiyun 
finetuneDQSI(struct ast_private * ast)713*4882a593Smuzhiyun static void finetuneDQSI(struct ast_private *ast)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun 	u32 dlli, dqsip, dqidly;
716*4882a593Smuzhiyun 	u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
717*4882a593Smuzhiyun 	u32 g_dqidly, g_dqsip, g_margin, g_side;
718*4882a593Smuzhiyun 	u16 pass[32][2][2];
719*4882a593Smuzhiyun 	char tag[2][76];
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	/* Disable DQI CBR */
722*4882a593Smuzhiyun 	reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
723*4882a593Smuzhiyun 	reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
724*4882a593Smuzhiyun 	reg_mcr18 &= 0x0000ffff;
725*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	for (dlli = 0; dlli < 76; dlli++) {
728*4882a593Smuzhiyun 		tag[0][dlli] = 0x0;
729*4882a593Smuzhiyun 		tag[1][dlli] = 0x0;
730*4882a593Smuzhiyun 	}
731*4882a593Smuzhiyun 	for (dqidly = 0; dqidly < 32; dqidly++) {
732*4882a593Smuzhiyun 		pass[dqidly][0][0] = 0xff;
733*4882a593Smuzhiyun 		pass[dqidly][0][1] = 0x0;
734*4882a593Smuzhiyun 		pass[dqidly][1][0] = 0xff;
735*4882a593Smuzhiyun 		pass[dqidly][1][1] = 0x0;
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 	for (dqidly = 0; dqidly < 32; dqidly++) {
738*4882a593Smuzhiyun 		passcnt[0] = passcnt[1] = 0;
739*4882a593Smuzhiyun 		for (dqsip = 0; dqsip < 2; dqsip++) {
740*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E000C, 0);
741*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23));
742*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
743*4882a593Smuzhiyun 			for (dlli = 0; dlli < 76; dlli++) {
744*4882a593Smuzhiyun 				ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
745*4882a593Smuzhiyun 				ast_moutdwm(ast, 0x1E6E0070, 0);
746*4882a593Smuzhiyun 				ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
747*4882a593Smuzhiyun 				if (cbr_scan3(ast)) {
748*4882a593Smuzhiyun 					if (dlli == 0)
749*4882a593Smuzhiyun 						break;
750*4882a593Smuzhiyun 					passcnt[dqsip]++;
751*4882a593Smuzhiyun 					tag[dqsip][dlli] = 'P';
752*4882a593Smuzhiyun 					if (dlli < pass[dqidly][dqsip][0])
753*4882a593Smuzhiyun 						pass[dqidly][dqsip][0] = (u16) dlli;
754*4882a593Smuzhiyun 					if (dlli > pass[dqidly][dqsip][1])
755*4882a593Smuzhiyun 						pass[dqidly][dqsip][1] = (u16) dlli;
756*4882a593Smuzhiyun 				} else if (passcnt[dqsip] >= 5)
757*4882a593Smuzhiyun 					break;
758*4882a593Smuzhiyun 				else {
759*4882a593Smuzhiyun 					pass[dqidly][dqsip][0] = 0xff;
760*4882a593Smuzhiyun 					pass[dqidly][dqsip][1] = 0x0;
761*4882a593Smuzhiyun 				}
762*4882a593Smuzhiyun 			}
763*4882a593Smuzhiyun 		}
764*4882a593Smuzhiyun 		if (passcnt[0] == 0 && passcnt[1] == 0)
765*4882a593Smuzhiyun 			dqidly++;
766*4882a593Smuzhiyun 	}
767*4882a593Smuzhiyun 	/* Search margin */
768*4882a593Smuzhiyun 	g_dqidly = g_dqsip = g_margin = g_side = 0;
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	for (dqidly = 0; dqidly < 32; dqidly++) {
771*4882a593Smuzhiyun 		for (dqsip = 0; dqsip < 2; dqsip++) {
772*4882a593Smuzhiyun 			if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
773*4882a593Smuzhiyun 				continue;
774*4882a593Smuzhiyun 			diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
775*4882a593Smuzhiyun 			if ((diff+2) < g_margin)
776*4882a593Smuzhiyun 				continue;
777*4882a593Smuzhiyun 			passcnt[0] = passcnt[1] = 0;
778*4882a593Smuzhiyun 			for (dlli = pass[dqidly][dqsip][0]; dlli > 0  && tag[dqsip][dlli] != 0; dlli--, passcnt[0]++);
779*4882a593Smuzhiyun 			for (dlli = pass[dqidly][dqsip][1]; dlli < 76 && tag[dqsip][dlli] != 0; dlli++, passcnt[1]++);
780*4882a593Smuzhiyun 			if (passcnt[0] > passcnt[1])
781*4882a593Smuzhiyun 				passcnt[0] = passcnt[1];
782*4882a593Smuzhiyun 			passcnt[1] = 0;
783*4882a593Smuzhiyun 			if (passcnt[0] > g_side)
784*4882a593Smuzhiyun 				passcnt[1] = passcnt[0] - g_side;
785*4882a593Smuzhiyun 			if (diff > (g_margin+1) && (passcnt[1] > 0 || passcnt[0] > 8)) {
786*4882a593Smuzhiyun 				g_margin = diff;
787*4882a593Smuzhiyun 				g_dqidly = dqidly;
788*4882a593Smuzhiyun 				g_dqsip  = dqsip;
789*4882a593Smuzhiyun 				g_side   = passcnt[0];
790*4882a593Smuzhiyun 			} else if (passcnt[1] > 1 && g_side < 8) {
791*4882a593Smuzhiyun 				if (diff > g_margin)
792*4882a593Smuzhiyun 					g_margin = diff;
793*4882a593Smuzhiyun 				g_dqidly = dqidly;
794*4882a593Smuzhiyun 				g_dqsip  = dqsip;
795*4882a593Smuzhiyun 				g_side   = passcnt[0];
796*4882a593Smuzhiyun 			}
797*4882a593Smuzhiyun 		}
798*4882a593Smuzhiyun 	}
799*4882a593Smuzhiyun 	reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
800*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun }
cbr_dll2(struct ast_private * ast,struct ast2300_dram_param * param)803*4882a593Smuzhiyun static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun 	u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
806*4882a593Smuzhiyun 	bool status = false;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	finetuneDQSI(ast);
809*4882a593Smuzhiyun 	if (finetuneDQI_L(ast, param) == false)
810*4882a593Smuzhiyun 		return status;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun CBR_START2:
813*4882a593Smuzhiyun 	dllmin[0] = dllmin[1] = 0xff;
814*4882a593Smuzhiyun 	dllmax[0] = dllmax[1] = 0x0;
815*4882a593Smuzhiyun 	passcnt = 0;
816*4882a593Smuzhiyun 	for (dlli = 0; dlli < 76; dlli++) {
817*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
818*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
819*4882a593Smuzhiyun 		data = cbr_scan(ast);
820*4882a593Smuzhiyun 		if (data != 0) {
821*4882a593Smuzhiyun 			if (data & 0x1) {
822*4882a593Smuzhiyun 				if (dllmin[0] > dlli) {
823*4882a593Smuzhiyun 					dllmin[0] = dlli;
824*4882a593Smuzhiyun 				}
825*4882a593Smuzhiyun 				if (dllmax[0] < dlli) {
826*4882a593Smuzhiyun 					dllmax[0] = dlli;
827*4882a593Smuzhiyun 				}
828*4882a593Smuzhiyun 			}
829*4882a593Smuzhiyun 			if (data & 0x2) {
830*4882a593Smuzhiyun 				if (dllmin[1] > dlli) {
831*4882a593Smuzhiyun 					dllmin[1] = dlli;
832*4882a593Smuzhiyun 				}
833*4882a593Smuzhiyun 				if (dllmax[1] < dlli) {
834*4882a593Smuzhiyun 					dllmax[1] = dlli;
835*4882a593Smuzhiyun 				}
836*4882a593Smuzhiyun 			}
837*4882a593Smuzhiyun 			passcnt++;
838*4882a593Smuzhiyun 		} else if (passcnt >= CBR_THRESHOLD) {
839*4882a593Smuzhiyun 			break;
840*4882a593Smuzhiyun 		}
841*4882a593Smuzhiyun 	}
842*4882a593Smuzhiyun 	if (retry++ > 10)
843*4882a593Smuzhiyun 		goto CBR_DONE2;
844*4882a593Smuzhiyun 	if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) {
845*4882a593Smuzhiyun 		goto CBR_START2;
846*4882a593Smuzhiyun 	}
847*4882a593Smuzhiyun 	if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) {
848*4882a593Smuzhiyun 		goto CBR_START2;
849*4882a593Smuzhiyun 	}
850*4882a593Smuzhiyun 	status = true;
851*4882a593Smuzhiyun CBR_DONE2:
852*4882a593Smuzhiyun 	dlli  = (dllmin[1] + dllmax[1]) >> 1;
853*4882a593Smuzhiyun 	dlli <<= 8;
854*4882a593Smuzhiyun 	dlli += (dllmin[0] + dllmax[0]) >> 1;
855*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16));
856*4882a593Smuzhiyun 	return status;
857*4882a593Smuzhiyun } /* CBRDLL2 */
858*4882a593Smuzhiyun 
get_ddr3_info(struct ast_private * ast,struct ast2300_dram_param * param)859*4882a593Smuzhiyun static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun 	u32 trap, trap_AC2, trap_MRS;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 	/* Ger trap info */
866*4882a593Smuzhiyun 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
867*4882a593Smuzhiyun 	trap_AC2  = 0x00020000 + (trap << 16);
868*4882a593Smuzhiyun 	trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
869*4882a593Smuzhiyun 	trap_MRS  = 0x00000010 + (trap << 4);
870*4882a593Smuzhiyun 	trap_MRS |= ((trap & 0x2) << 18);
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	param->reg_MADJ       = 0x00034C4C;
873*4882a593Smuzhiyun 	param->reg_SADJ       = 0x00001800;
874*4882a593Smuzhiyun 	param->reg_DRV        = 0x000000F0;
875*4882a593Smuzhiyun 	param->reg_PERIOD     = param->dram_freq;
876*4882a593Smuzhiyun 	param->rodt           = 0;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	switch (param->dram_freq) {
879*4882a593Smuzhiyun 	case 336:
880*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
881*4882a593Smuzhiyun 		param->wodt          = 0;
882*4882a593Smuzhiyun 		param->reg_AC1       = 0x22202725;
883*4882a593Smuzhiyun 		param->reg_AC2       = 0xAA007613 | trap_AC2;
884*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000BA;
885*4882a593Smuzhiyun 		param->reg_MRS       = 0x04001400 | trap_MRS;
886*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000000;
887*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000023;
888*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000074;
889*4882a593Smuzhiyun 		param->reg_FREQ      = 0x00004DC0;
890*4882a593Smuzhiyun 		param->madj_max      = 96;
891*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
892*4882a593Smuzhiyun 		switch (param->dram_chipid) {
893*4882a593Smuzhiyun 		default:
894*4882a593Smuzhiyun 		case AST_DRAM_512Mx16:
895*4882a593Smuzhiyun 		case AST_DRAM_1Gx16:
896*4882a593Smuzhiyun 			param->reg_AC2   = 0xAA007613 | trap_AC2;
897*4882a593Smuzhiyun 			break;
898*4882a593Smuzhiyun 		case AST_DRAM_2Gx16:
899*4882a593Smuzhiyun 			param->reg_AC2   = 0xAA00761C | trap_AC2;
900*4882a593Smuzhiyun 			break;
901*4882a593Smuzhiyun 		case AST_DRAM_4Gx16:
902*4882a593Smuzhiyun 			param->reg_AC2   = 0xAA007636 | trap_AC2;
903*4882a593Smuzhiyun 			break;
904*4882a593Smuzhiyun 		}
905*4882a593Smuzhiyun 		break;
906*4882a593Smuzhiyun 	default:
907*4882a593Smuzhiyun 	case 396:
908*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
909*4882a593Smuzhiyun 		param->wodt          = 1;
910*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302825;
911*4882a593Smuzhiyun 		param->reg_AC2       = 0xCC009617 | trap_AC2;
912*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000E2;
913*4882a593Smuzhiyun 		param->reg_MRS       = 0x04001600 | trap_MRS;
914*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000000;
915*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000034;
916*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000FA;
917*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000089;
918*4882a593Smuzhiyun 		param->reg_FREQ      = 0x00005040;
919*4882a593Smuzhiyun 		param->madj_max      = 96;
920*4882a593Smuzhiyun 		param->dll2_finetune_step = 4;
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 		switch (param->dram_chipid) {
923*4882a593Smuzhiyun 		default:
924*4882a593Smuzhiyun 		case AST_DRAM_512Mx16:
925*4882a593Smuzhiyun 		case AST_DRAM_1Gx16:
926*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC009617 | trap_AC2;
927*4882a593Smuzhiyun 			break;
928*4882a593Smuzhiyun 		case AST_DRAM_2Gx16:
929*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC009622 | trap_AC2;
930*4882a593Smuzhiyun 			break;
931*4882a593Smuzhiyun 		case AST_DRAM_4Gx16:
932*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00963F | trap_AC2;
933*4882a593Smuzhiyun 			break;
934*4882a593Smuzhiyun 		}
935*4882a593Smuzhiyun 		break;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	case 408:
938*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
939*4882a593Smuzhiyun 		param->wodt          = 1;
940*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302825;
941*4882a593Smuzhiyun 		param->reg_AC2       = 0xCC009617 | trap_AC2;
942*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000E2;
943*4882a593Smuzhiyun 		param->reg_MRS       = 0x04001600 | trap_MRS;
944*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000000;
945*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000023;
946*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000FA;
947*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000089;
948*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000050C0;
949*4882a593Smuzhiyun 		param->madj_max      = 96;
950*4882a593Smuzhiyun 		param->dll2_finetune_step = 4;
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 		switch (param->dram_chipid) {
953*4882a593Smuzhiyun 		default:
954*4882a593Smuzhiyun 		case AST_DRAM_512Mx16:
955*4882a593Smuzhiyun 		case AST_DRAM_1Gx16:
956*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC009617 | trap_AC2;
957*4882a593Smuzhiyun 			break;
958*4882a593Smuzhiyun 		case AST_DRAM_2Gx16:
959*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC009622 | trap_AC2;
960*4882a593Smuzhiyun 			break;
961*4882a593Smuzhiyun 		case AST_DRAM_4Gx16:
962*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00963F | trap_AC2;
963*4882a593Smuzhiyun 			break;
964*4882a593Smuzhiyun 		}
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 		break;
967*4882a593Smuzhiyun 	case 456:
968*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
969*4882a593Smuzhiyun 		param->wodt          = 0;
970*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302926;
971*4882a593Smuzhiyun 		param->reg_AC2       = 0xCD44961A;
972*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000FC;
973*4882a593Smuzhiyun 		param->reg_MRS       = 0x00081830;
974*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000000;
975*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000045;
976*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000097;
977*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000052C0;
978*4882a593Smuzhiyun 		param->madj_max      = 88;
979*4882a593Smuzhiyun 		param->dll2_finetune_step = 4;
980*4882a593Smuzhiyun 		break;
981*4882a593Smuzhiyun 	case 504:
982*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0270);
983*4882a593Smuzhiyun 		param->wodt          = 1;
984*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302926;
985*4882a593Smuzhiyun 		param->reg_AC2       = 0xDE44A61D;
986*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x00000117;
987*4882a593Smuzhiyun 		param->reg_MRS       = 0x00081A30;
988*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000000;
989*4882a593Smuzhiyun 		param->reg_IOZ       = 0x070000BB;
990*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x000000A0;
991*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000054C0;
992*4882a593Smuzhiyun 		param->madj_max      = 79;
993*4882a593Smuzhiyun 		param->dll2_finetune_step = 4;
994*4882a593Smuzhiyun 		break;
995*4882a593Smuzhiyun 	case 528:
996*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0290);
997*4882a593Smuzhiyun 		param->wodt          = 1;
998*4882a593Smuzhiyun 		param->rodt          = 1;
999*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302926;
1000*4882a593Smuzhiyun 		param->reg_AC2       = 0xEF44B61E;
1001*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x00000125;
1002*4882a593Smuzhiyun 		param->reg_MRS       = 0x00081A30;
1003*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000040;
1004*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000F5;
1005*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000023;
1006*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000088;
1007*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000055C0;
1008*4882a593Smuzhiyun 		param->madj_max      = 76;
1009*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1010*4882a593Smuzhiyun 		break;
1011*4882a593Smuzhiyun 	case 576:
1012*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1013*4882a593Smuzhiyun 		param->reg_MADJ      = 0x00136868;
1014*4882a593Smuzhiyun 		param->reg_SADJ      = 0x00004534;
1015*4882a593Smuzhiyun 		param->wodt          = 1;
1016*4882a593Smuzhiyun 		param->rodt          = 1;
1017*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302A37;
1018*4882a593Smuzhiyun 		param->reg_AC2       = 0xEF56B61E;
1019*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x0000013F;
1020*4882a593Smuzhiyun 		param->reg_MRS       = 0x00101A50;
1021*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000040;
1022*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000FA;
1023*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000023;
1024*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000078;
1025*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000057C0;
1026*4882a593Smuzhiyun 		param->madj_max      = 136;
1027*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1028*4882a593Smuzhiyun 		break;
1029*4882a593Smuzhiyun 	case 600:
1030*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
1031*4882a593Smuzhiyun 		param->reg_MADJ      = 0x00136868;
1032*4882a593Smuzhiyun 		param->reg_SADJ      = 0x00004534;
1033*4882a593Smuzhiyun 		param->wodt          = 1;
1034*4882a593Smuzhiyun 		param->rodt          = 1;
1035*4882a593Smuzhiyun 		param->reg_AC1       = 0x32302A37;
1036*4882a593Smuzhiyun 		param->reg_AC2       = 0xDF56B61F;
1037*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x0000014D;
1038*4882a593Smuzhiyun 		param->reg_MRS       = 0x00101A50;
1039*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000004;
1040*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000F5;
1041*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000023;
1042*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000078;
1043*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000058C0;
1044*4882a593Smuzhiyun 		param->madj_max      = 132;
1045*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1046*4882a593Smuzhiyun 		break;
1047*4882a593Smuzhiyun 	case 624:
1048*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0160);
1049*4882a593Smuzhiyun 		param->reg_MADJ      = 0x00136868;
1050*4882a593Smuzhiyun 		param->reg_SADJ      = 0x00004534;
1051*4882a593Smuzhiyun 		param->wodt          = 1;
1052*4882a593Smuzhiyun 		param->rodt          = 1;
1053*4882a593Smuzhiyun 		param->reg_AC1       = 0x32302A37;
1054*4882a593Smuzhiyun 		param->reg_AC2       = 0xEF56B621;
1055*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x0000015A;
1056*4882a593Smuzhiyun 		param->reg_MRS       = 0x02101A50;
1057*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000004;
1058*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000F5;
1059*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000034;
1060*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000078;
1061*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000059C0;
1062*4882a593Smuzhiyun 		param->madj_max      = 128;
1063*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1064*4882a593Smuzhiyun 		break;
1065*4882a593Smuzhiyun 	} /* switch freq */
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun 	switch (param->dram_chipid) {
1068*4882a593Smuzhiyun 	case AST_DRAM_512Mx16:
1069*4882a593Smuzhiyun 		param->dram_config = 0x130;
1070*4882a593Smuzhiyun 		break;
1071*4882a593Smuzhiyun 	default:
1072*4882a593Smuzhiyun 	case AST_DRAM_1Gx16:
1073*4882a593Smuzhiyun 		param->dram_config = 0x131;
1074*4882a593Smuzhiyun 		break;
1075*4882a593Smuzhiyun 	case AST_DRAM_2Gx16:
1076*4882a593Smuzhiyun 		param->dram_config = 0x132;
1077*4882a593Smuzhiyun 		break;
1078*4882a593Smuzhiyun 	case AST_DRAM_4Gx16:
1079*4882a593Smuzhiyun 		param->dram_config = 0x133;
1080*4882a593Smuzhiyun 		break;
1081*4882a593Smuzhiyun 	} /* switch size */
1082*4882a593Smuzhiyun 
1083*4882a593Smuzhiyun 	switch (param->vram_size) {
1084*4882a593Smuzhiyun 	default:
1085*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_8M:
1086*4882a593Smuzhiyun 		param->dram_config |= 0x00;
1087*4882a593Smuzhiyun 		break;
1088*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_16M:
1089*4882a593Smuzhiyun 		param->dram_config |= 0x04;
1090*4882a593Smuzhiyun 		break;
1091*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_32M:
1092*4882a593Smuzhiyun 		param->dram_config |= 0x08;
1093*4882a593Smuzhiyun 		break;
1094*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_64M:
1095*4882a593Smuzhiyun 		param->dram_config |= 0x0c;
1096*4882a593Smuzhiyun 		break;
1097*4882a593Smuzhiyun 	}
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun 
ddr3_init(struct ast_private * ast,struct ast2300_dram_param * param)1101*4882a593Smuzhiyun static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param)
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun 	u32 data, data2, retry = 0;
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun ddr3_init_start:
1106*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
1107*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
1108*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
1109*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
1110*4882a593Smuzhiyun 	udelay(10);
1111*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
1112*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1113*4882a593Smuzhiyun 	udelay(10);
1114*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1115*4882a593Smuzhiyun 	udelay(10);
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
1118*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
1119*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
1120*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
1121*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
1122*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
1123*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
1124*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
1125*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
1126*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
1127*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
1128*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
1129*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
1130*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
1131*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
1132*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1133*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1134*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0054, 0);
1135*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
1136*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
1137*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1138*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
1139*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
1140*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1141*4882a593Smuzhiyun 	/* Wait MCLK2X lock to MCLK */
1142*4882a593Smuzhiyun 	do {
1143*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E001C);
1144*4882a593Smuzhiyun 	} while (!(data & 0x08000000));
1145*4882a593Smuzhiyun 	data = ast_mindwm(ast, 0x1E6E001C);
1146*4882a593Smuzhiyun 	data = (data >> 8) & 0xff;
1147*4882a593Smuzhiyun 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
1148*4882a593Smuzhiyun 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1149*4882a593Smuzhiyun 		if ((data2 & 0xff) > param->madj_max) {
1150*4882a593Smuzhiyun 			break;
1151*4882a593Smuzhiyun 		}
1152*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0064, data2);
1153*4882a593Smuzhiyun 		if (data2 & 0x00100000) {
1154*4882a593Smuzhiyun 			data2 = ((data2 & 0xff) >> 3) + 3;
1155*4882a593Smuzhiyun 		} else {
1156*4882a593Smuzhiyun 			data2 = ((data2 & 0xff) >> 2) + 5;
1157*4882a593Smuzhiyun 		}
1158*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1159*4882a593Smuzhiyun 		data2 += data & 0xff;
1160*4882a593Smuzhiyun 		data = data | (data2 << 8);
1161*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0068, data);
1162*4882a593Smuzhiyun 		udelay(10);
1163*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1164*4882a593Smuzhiyun 		udelay(10);
1165*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
1166*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0018, data);
1167*4882a593Smuzhiyun 		data = data | 0x200;
1168*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0018, data);
1169*4882a593Smuzhiyun 		do {
1170*4882a593Smuzhiyun 			data = ast_mindwm(ast, 0x1E6E001C);
1171*4882a593Smuzhiyun 		} while (!(data & 0x08000000));
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E001C);
1174*4882a593Smuzhiyun 		data = (data >> 8) & 0xff;
1175*4882a593Smuzhiyun 	}
1176*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
1177*4882a593Smuzhiyun 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
1178*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, data);
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
1181*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
1182*4882a593Smuzhiyun 	udelay(50);
1183*4882a593Smuzhiyun 	/* Mode Register Setting */
1184*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
1185*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
1186*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
1187*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
1188*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1189*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1190*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
1191*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
1192*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
1195*4882a593Smuzhiyun 	data = 0;
1196*4882a593Smuzhiyun 	if (param->wodt) {
1197*4882a593Smuzhiyun 		data = 0x300;
1198*4882a593Smuzhiyun 	}
1199*4882a593Smuzhiyun 	if (param->rodt) {
1200*4882a593Smuzhiyun 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1201*4882a593Smuzhiyun 	}
1202*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun 	/* Calibrate the DQSI delay */
1205*4882a593Smuzhiyun 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1206*4882a593Smuzhiyun 		goto ddr3_init_start;
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1209*4882a593Smuzhiyun 	/* ECC Memory Initialization */
1210*4882a593Smuzhiyun #ifdef ECC
1211*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1212*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1213*4882a593Smuzhiyun 	do {
1214*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E0070);
1215*4882a593Smuzhiyun 	} while (!(data & 0x00001000));
1216*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1217*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1218*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1219*4882a593Smuzhiyun #endif
1220*4882a593Smuzhiyun 
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun 
get_ddr2_info(struct ast_private * ast,struct ast2300_dram_param * param)1224*4882a593Smuzhiyun static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param)
1225*4882a593Smuzhiyun {
1226*4882a593Smuzhiyun 	u32 trap, trap_AC2, trap_MRS;
1227*4882a593Smuzhiyun 
1228*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
1229*4882a593Smuzhiyun 
1230*4882a593Smuzhiyun 	/* Ger trap info */
1231*4882a593Smuzhiyun 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
1232*4882a593Smuzhiyun 	trap_AC2  = (trap << 20) | (trap << 16);
1233*4882a593Smuzhiyun 	trap_AC2 += 0x00110000;
1234*4882a593Smuzhiyun 	trap_MRS  = 0x00000040 | (trap << 4);
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	param->reg_MADJ       = 0x00034C4C;
1238*4882a593Smuzhiyun 	param->reg_SADJ       = 0x00001800;
1239*4882a593Smuzhiyun 	param->reg_DRV        = 0x000000F0;
1240*4882a593Smuzhiyun 	param->reg_PERIOD     = param->dram_freq;
1241*4882a593Smuzhiyun 	param->rodt           = 0;
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	switch (param->dram_freq) {
1244*4882a593Smuzhiyun 	case 264:
1245*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0130);
1246*4882a593Smuzhiyun 		param->wodt          = 0;
1247*4882a593Smuzhiyun 		param->reg_AC1       = 0x11101513;
1248*4882a593Smuzhiyun 		param->reg_AC2       = 0x78117011;
1249*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x00000092;
1250*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000842;
1251*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000000;
1252*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000F0;
1253*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000034;
1254*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x0000005A;
1255*4882a593Smuzhiyun 		param->reg_FREQ      = 0x00004AC0;
1256*4882a593Smuzhiyun 		param->madj_max      = 138;
1257*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1258*4882a593Smuzhiyun 		break;
1259*4882a593Smuzhiyun 	case 336:
1260*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
1261*4882a593Smuzhiyun 		param->wodt          = 1;
1262*4882a593Smuzhiyun 		param->reg_AC1       = 0x22202613;
1263*4882a593Smuzhiyun 		param->reg_AC2       = 0xAA009016 | trap_AC2;
1264*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000BA;
1265*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000A02 | trap_MRS;
1266*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000040;
1267*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000FA;
1268*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000034;
1269*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000074;
1270*4882a593Smuzhiyun 		param->reg_FREQ      = 0x00004DC0;
1271*4882a593Smuzhiyun 		param->madj_max      = 96;
1272*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1273*4882a593Smuzhiyun 		switch (param->dram_chipid) {
1274*4882a593Smuzhiyun 		default:
1275*4882a593Smuzhiyun 		case AST_DRAM_512Mx16:
1276*4882a593Smuzhiyun 			param->reg_AC2   = 0xAA009012 | trap_AC2;
1277*4882a593Smuzhiyun 			break;
1278*4882a593Smuzhiyun 		case AST_DRAM_1Gx16:
1279*4882a593Smuzhiyun 			param->reg_AC2   = 0xAA009016 | trap_AC2;
1280*4882a593Smuzhiyun 			break;
1281*4882a593Smuzhiyun 		case AST_DRAM_2Gx16:
1282*4882a593Smuzhiyun 			param->reg_AC2   = 0xAA009023 | trap_AC2;
1283*4882a593Smuzhiyun 			break;
1284*4882a593Smuzhiyun 		case AST_DRAM_4Gx16:
1285*4882a593Smuzhiyun 			param->reg_AC2   = 0xAA00903B | trap_AC2;
1286*4882a593Smuzhiyun 			break;
1287*4882a593Smuzhiyun 		}
1288*4882a593Smuzhiyun 		break;
1289*4882a593Smuzhiyun 	default:
1290*4882a593Smuzhiyun 	case 396:
1291*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
1292*4882a593Smuzhiyun 		param->wodt          = 1;
1293*4882a593Smuzhiyun 		param->rodt          = 0;
1294*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302714;
1295*4882a593Smuzhiyun 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1296*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000E2;
1297*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1298*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000040;
1299*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000FA;
1300*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000034;
1301*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000089;
1302*4882a593Smuzhiyun 		param->reg_FREQ      = 0x00005040;
1303*4882a593Smuzhiyun 		param->madj_max      = 96;
1304*4882a593Smuzhiyun 		param->dll2_finetune_step = 4;
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 		switch (param->dram_chipid) {
1307*4882a593Smuzhiyun 		case AST_DRAM_512Mx16:
1308*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1309*4882a593Smuzhiyun 			break;
1310*4882a593Smuzhiyun 		default:
1311*4882a593Smuzhiyun 		case AST_DRAM_1Gx16:
1312*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1313*4882a593Smuzhiyun 			break;
1314*4882a593Smuzhiyun 		case AST_DRAM_2Gx16:
1315*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1316*4882a593Smuzhiyun 			break;
1317*4882a593Smuzhiyun 		case AST_DRAM_4Gx16:
1318*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1319*4882a593Smuzhiyun 			break;
1320*4882a593Smuzhiyun 		}
1321*4882a593Smuzhiyun 
1322*4882a593Smuzhiyun 		break;
1323*4882a593Smuzhiyun 
1324*4882a593Smuzhiyun 	case 408:
1325*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
1326*4882a593Smuzhiyun 		param->wodt          = 1;
1327*4882a593Smuzhiyun 		param->rodt          = 0;
1328*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302714;
1329*4882a593Smuzhiyun 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1330*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000E2;
1331*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1332*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000040;
1333*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000FA;
1334*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000034;
1335*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000089;
1336*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000050C0;
1337*4882a593Smuzhiyun 		param->madj_max      = 96;
1338*4882a593Smuzhiyun 		param->dll2_finetune_step = 4;
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun 		switch (param->dram_chipid) {
1341*4882a593Smuzhiyun 		case AST_DRAM_512Mx16:
1342*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1343*4882a593Smuzhiyun 			break;
1344*4882a593Smuzhiyun 		default:
1345*4882a593Smuzhiyun 		case AST_DRAM_1Gx16:
1346*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1347*4882a593Smuzhiyun 			break;
1348*4882a593Smuzhiyun 		case AST_DRAM_2Gx16:
1349*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1350*4882a593Smuzhiyun 			break;
1351*4882a593Smuzhiyun 		case AST_DRAM_4Gx16:
1352*4882a593Smuzhiyun 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1353*4882a593Smuzhiyun 			break;
1354*4882a593Smuzhiyun 		}
1355*4882a593Smuzhiyun 
1356*4882a593Smuzhiyun 		break;
1357*4882a593Smuzhiyun 	case 456:
1358*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
1359*4882a593Smuzhiyun 		param->wodt          = 0;
1360*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302815;
1361*4882a593Smuzhiyun 		param->reg_AC2       = 0xCD44B01E;
1362*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x000000FC;
1363*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000E72;
1364*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000000;
1365*4882a593Smuzhiyun 		param->reg_DRV       = 0x00000000;
1366*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000034;
1367*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x00000097;
1368*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000052C0;
1369*4882a593Smuzhiyun 		param->madj_max      = 88;
1370*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1371*4882a593Smuzhiyun 		break;
1372*4882a593Smuzhiyun 	case 504:
1373*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0261);
1374*4882a593Smuzhiyun 		param->wodt          = 1;
1375*4882a593Smuzhiyun 		param->rodt          = 1;
1376*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302815;
1377*4882a593Smuzhiyun 		param->reg_AC2       = 0xDE44C022;
1378*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x00000117;
1379*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000E72;
1380*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000040;
1381*4882a593Smuzhiyun 		param->reg_DRV       = 0x0000000A;
1382*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000045;
1383*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x000000A0;
1384*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000054C0;
1385*4882a593Smuzhiyun 		param->madj_max      = 79;
1386*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1387*4882a593Smuzhiyun 		break;
1388*4882a593Smuzhiyun 	case 528:
1389*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0120);
1390*4882a593Smuzhiyun 		param->wodt          = 1;
1391*4882a593Smuzhiyun 		param->rodt          = 1;
1392*4882a593Smuzhiyun 		param->reg_AC1       = 0x33302815;
1393*4882a593Smuzhiyun 		param->reg_AC2       = 0xEF44D024;
1394*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x00000125;
1395*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000E72;
1396*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000004;
1397*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000F9;
1398*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000045;
1399*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x000000A7;
1400*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000055C0;
1401*4882a593Smuzhiyun 		param->madj_max      = 76;
1402*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1403*4882a593Smuzhiyun 		break;
1404*4882a593Smuzhiyun 	case 552:
1405*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
1406*4882a593Smuzhiyun 		param->wodt          = 1;
1407*4882a593Smuzhiyun 		param->rodt          = 1;
1408*4882a593Smuzhiyun 		param->reg_AC1       = 0x43402915;
1409*4882a593Smuzhiyun 		param->reg_AC2       = 0xFF44E025;
1410*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x00000132;
1411*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000E72;
1412*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000040;
1413*4882a593Smuzhiyun 		param->reg_DRV       = 0x0000000A;
1414*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000045;
1415*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x000000AD;
1416*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000056C0;
1417*4882a593Smuzhiyun 		param->madj_max      = 76;
1418*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1419*4882a593Smuzhiyun 		break;
1420*4882a593Smuzhiyun 	case 576:
1421*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1422*4882a593Smuzhiyun 		param->wodt          = 1;
1423*4882a593Smuzhiyun 		param->rodt          = 1;
1424*4882a593Smuzhiyun 		param->reg_AC1       = 0x43402915;
1425*4882a593Smuzhiyun 		param->reg_AC2       = 0xFF44E027;
1426*4882a593Smuzhiyun 		param->reg_DQSIC     = 0x0000013F;
1427*4882a593Smuzhiyun 		param->reg_MRS       = 0x00000E72;
1428*4882a593Smuzhiyun 		param->reg_EMRS      = 0x00000004;
1429*4882a593Smuzhiyun 		param->reg_DRV       = 0x000000F5;
1430*4882a593Smuzhiyun 		param->reg_IOZ       = 0x00000045;
1431*4882a593Smuzhiyun 		param->reg_DQIDLY    = 0x000000B3;
1432*4882a593Smuzhiyun 		param->reg_FREQ      = 0x000057C0;
1433*4882a593Smuzhiyun 		param->madj_max      = 76;
1434*4882a593Smuzhiyun 		param->dll2_finetune_step = 3;
1435*4882a593Smuzhiyun 		break;
1436*4882a593Smuzhiyun 	}
1437*4882a593Smuzhiyun 
1438*4882a593Smuzhiyun 	switch (param->dram_chipid) {
1439*4882a593Smuzhiyun 	case AST_DRAM_512Mx16:
1440*4882a593Smuzhiyun 		param->dram_config = 0x100;
1441*4882a593Smuzhiyun 		break;
1442*4882a593Smuzhiyun 	default:
1443*4882a593Smuzhiyun 	case AST_DRAM_1Gx16:
1444*4882a593Smuzhiyun 		param->dram_config = 0x121;
1445*4882a593Smuzhiyun 		break;
1446*4882a593Smuzhiyun 	case AST_DRAM_2Gx16:
1447*4882a593Smuzhiyun 		param->dram_config = 0x122;
1448*4882a593Smuzhiyun 		break;
1449*4882a593Smuzhiyun 	case AST_DRAM_4Gx16:
1450*4882a593Smuzhiyun 		param->dram_config = 0x123;
1451*4882a593Smuzhiyun 		break;
1452*4882a593Smuzhiyun 	} /* switch size */
1453*4882a593Smuzhiyun 
1454*4882a593Smuzhiyun 	switch (param->vram_size) {
1455*4882a593Smuzhiyun 	default:
1456*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_8M:
1457*4882a593Smuzhiyun 		param->dram_config |= 0x00;
1458*4882a593Smuzhiyun 		break;
1459*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_16M:
1460*4882a593Smuzhiyun 		param->dram_config |= 0x04;
1461*4882a593Smuzhiyun 		break;
1462*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_32M:
1463*4882a593Smuzhiyun 		param->dram_config |= 0x08;
1464*4882a593Smuzhiyun 		break;
1465*4882a593Smuzhiyun 	case AST_VIDMEM_SIZE_64M:
1466*4882a593Smuzhiyun 		param->dram_config |= 0x0c;
1467*4882a593Smuzhiyun 		break;
1468*4882a593Smuzhiyun 	}
1469*4882a593Smuzhiyun }
1470*4882a593Smuzhiyun 
ddr2_init(struct ast_private * ast,struct ast2300_dram_param * param)1471*4882a593Smuzhiyun static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param)
1472*4882a593Smuzhiyun {
1473*4882a593Smuzhiyun 	u32 data, data2, retry = 0;
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun ddr2_init_start:
1476*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
1477*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
1478*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
1479*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
1480*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1481*4882a593Smuzhiyun 	udelay(10);
1482*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1483*4882a593Smuzhiyun 	udelay(10);
1484*4882a593Smuzhiyun 
1485*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
1486*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
1487*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
1488*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
1489*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
1490*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
1491*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
1492*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
1493*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
1494*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
1495*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
1496*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
1497*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
1498*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
1499*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
1500*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1501*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1502*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0054, 0);
1503*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
1504*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
1505*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1506*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
1507*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
1508*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1509*4882a593Smuzhiyun 
1510*4882a593Smuzhiyun 	/* Wait MCLK2X lock to MCLK */
1511*4882a593Smuzhiyun 	do {
1512*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E001C);
1513*4882a593Smuzhiyun 	} while (!(data & 0x08000000));
1514*4882a593Smuzhiyun 	data = ast_mindwm(ast, 0x1E6E001C);
1515*4882a593Smuzhiyun 	data = (data >> 8) & 0xff;
1516*4882a593Smuzhiyun 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
1517*4882a593Smuzhiyun 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1518*4882a593Smuzhiyun 		if ((data2 & 0xff) > param->madj_max) {
1519*4882a593Smuzhiyun 			break;
1520*4882a593Smuzhiyun 		}
1521*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0064, data2);
1522*4882a593Smuzhiyun 		if (data2 & 0x00100000) {
1523*4882a593Smuzhiyun 			data2 = ((data2 & 0xff) >> 3) + 3;
1524*4882a593Smuzhiyun 		} else {
1525*4882a593Smuzhiyun 			data2 = ((data2 & 0xff) >> 2) + 5;
1526*4882a593Smuzhiyun 		}
1527*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1528*4882a593Smuzhiyun 		data2 += data & 0xff;
1529*4882a593Smuzhiyun 		data = data | (data2 << 8);
1530*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0068, data);
1531*4882a593Smuzhiyun 		udelay(10);
1532*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1533*4882a593Smuzhiyun 		udelay(10);
1534*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
1535*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0018, data);
1536*4882a593Smuzhiyun 		data = data | 0x200;
1537*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E0018, data);
1538*4882a593Smuzhiyun 		do {
1539*4882a593Smuzhiyun 			data = ast_mindwm(ast, 0x1E6E001C);
1540*4882a593Smuzhiyun 		} while (!(data & 0x08000000));
1541*4882a593Smuzhiyun 
1542*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E001C);
1543*4882a593Smuzhiyun 		data = (data >> 8) & 0xff;
1544*4882a593Smuzhiyun 	}
1545*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
1546*4882a593Smuzhiyun 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
1547*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, data);
1548*4882a593Smuzhiyun 
1549*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
1550*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1551*4882a593Smuzhiyun 	udelay(50);
1552*4882a593Smuzhiyun 	/* Mode Register Setting */
1553*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
1554*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
1555*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
1556*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
1557*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1558*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1559*4882a593Smuzhiyun 
1560*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
1561*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
1562*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1563*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
1564*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1565*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
1566*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1567*4882a593Smuzhiyun 
1568*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
1569*4882a593Smuzhiyun 	data = 0;
1570*4882a593Smuzhiyun 	if (param->wodt) {
1571*4882a593Smuzhiyun 		data = 0x500;
1572*4882a593Smuzhiyun 	}
1573*4882a593Smuzhiyun 	if (param->rodt) {
1574*4882a593Smuzhiyun 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1575*4882a593Smuzhiyun 	}
1576*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
1577*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun 	/* Calibrate the DQSI delay */
1580*4882a593Smuzhiyun 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1581*4882a593Smuzhiyun 		goto ddr2_init_start;
1582*4882a593Smuzhiyun 
1583*4882a593Smuzhiyun 	/* ECC Memory Initialization */
1584*4882a593Smuzhiyun #ifdef ECC
1585*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1586*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1587*4882a593Smuzhiyun 	do {
1588*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E0070);
1589*4882a593Smuzhiyun 	} while (!(data & 0x00001000));
1590*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1591*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1592*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1593*4882a593Smuzhiyun #endif
1594*4882a593Smuzhiyun 
1595*4882a593Smuzhiyun }
1596*4882a593Smuzhiyun 
ast_post_chip_2300(struct drm_device * dev)1597*4882a593Smuzhiyun static void ast_post_chip_2300(struct drm_device *dev)
1598*4882a593Smuzhiyun {
1599*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
1600*4882a593Smuzhiyun 	struct ast2300_dram_param param;
1601*4882a593Smuzhiyun 	u32 temp;
1602*4882a593Smuzhiyun 	u8 reg;
1603*4882a593Smuzhiyun 
1604*4882a593Smuzhiyun 	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1605*4882a593Smuzhiyun 	if ((reg & 0x80) == 0) {/* vga only */
1606*4882a593Smuzhiyun 		ast_write32(ast, 0xf004, 0x1e6e0000);
1607*4882a593Smuzhiyun 		ast_write32(ast, 0xf000, 0x1);
1608*4882a593Smuzhiyun 		ast_write32(ast, 0x12000, 0x1688a8a8);
1609*4882a593Smuzhiyun 		do {
1610*4882a593Smuzhiyun 			;
1611*4882a593Smuzhiyun 		} while (ast_read32(ast, 0x12000) != 0x1);
1612*4882a593Smuzhiyun 
1613*4882a593Smuzhiyun 		ast_write32(ast, 0x10000, 0xfc600309);
1614*4882a593Smuzhiyun 		do {
1615*4882a593Smuzhiyun 			;
1616*4882a593Smuzhiyun 		} while (ast_read32(ast, 0x10000) != 0x1);
1617*4882a593Smuzhiyun 
1618*4882a593Smuzhiyun 		/* Slow down CPU/AHB CLK in VGA only mode */
1619*4882a593Smuzhiyun 		temp = ast_read32(ast, 0x12008);
1620*4882a593Smuzhiyun 		temp |= 0x73;
1621*4882a593Smuzhiyun 		ast_write32(ast, 0x12008, temp);
1622*4882a593Smuzhiyun 
1623*4882a593Smuzhiyun 		param.dram_freq = 396;
1624*4882a593Smuzhiyun 		param.dram_type = AST_DDR3;
1625*4882a593Smuzhiyun 		temp = ast_mindwm(ast, 0x1e6e2070);
1626*4882a593Smuzhiyun 		if (temp & 0x01000000)
1627*4882a593Smuzhiyun 			param.dram_type = AST_DDR2;
1628*4882a593Smuzhiyun                 switch (temp & 0x18000000) {
1629*4882a593Smuzhiyun 		case 0:
1630*4882a593Smuzhiyun 			param.dram_chipid = AST_DRAM_512Mx16;
1631*4882a593Smuzhiyun 			break;
1632*4882a593Smuzhiyun 		default:
1633*4882a593Smuzhiyun 		case 0x08000000:
1634*4882a593Smuzhiyun 			param.dram_chipid = AST_DRAM_1Gx16;
1635*4882a593Smuzhiyun 			break;
1636*4882a593Smuzhiyun 		case 0x10000000:
1637*4882a593Smuzhiyun 			param.dram_chipid = AST_DRAM_2Gx16;
1638*4882a593Smuzhiyun 			break;
1639*4882a593Smuzhiyun 		case 0x18000000:
1640*4882a593Smuzhiyun 			param.dram_chipid = AST_DRAM_4Gx16;
1641*4882a593Smuzhiyun 			break;
1642*4882a593Smuzhiyun 		}
1643*4882a593Smuzhiyun                 switch (temp & 0x0c) {
1644*4882a593Smuzhiyun                 default:
1645*4882a593Smuzhiyun 		case 0x00:
1646*4882a593Smuzhiyun 			param.vram_size = AST_VIDMEM_SIZE_8M;
1647*4882a593Smuzhiyun 			break;
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 		case 0x04:
1650*4882a593Smuzhiyun 			param.vram_size = AST_VIDMEM_SIZE_16M;
1651*4882a593Smuzhiyun 			break;
1652*4882a593Smuzhiyun 
1653*4882a593Smuzhiyun 		case 0x08:
1654*4882a593Smuzhiyun 			param.vram_size = AST_VIDMEM_SIZE_32M;
1655*4882a593Smuzhiyun 			break;
1656*4882a593Smuzhiyun 
1657*4882a593Smuzhiyun 		case 0x0c:
1658*4882a593Smuzhiyun 			param.vram_size = AST_VIDMEM_SIZE_64M;
1659*4882a593Smuzhiyun 			break;
1660*4882a593Smuzhiyun 		}
1661*4882a593Smuzhiyun 
1662*4882a593Smuzhiyun 		if (param.dram_type == AST_DDR3) {
1663*4882a593Smuzhiyun 			get_ddr3_info(ast, &param);
1664*4882a593Smuzhiyun 			ddr3_init(ast, &param);
1665*4882a593Smuzhiyun 		} else {
1666*4882a593Smuzhiyun 			get_ddr2_info(ast, &param);
1667*4882a593Smuzhiyun 			ddr2_init(ast, &param);
1668*4882a593Smuzhiyun 		}
1669*4882a593Smuzhiyun 
1670*4882a593Smuzhiyun 		temp = ast_mindwm(ast, 0x1e6e2040);
1671*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
1672*4882a593Smuzhiyun 	}
1673*4882a593Smuzhiyun 
1674*4882a593Smuzhiyun 	/* wait ready */
1675*4882a593Smuzhiyun 	do {
1676*4882a593Smuzhiyun 		reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1677*4882a593Smuzhiyun 	} while ((reg & 0x40) == 0);
1678*4882a593Smuzhiyun }
1679*4882a593Smuzhiyun 
cbr_test_2500(struct ast_private * ast)1680*4882a593Smuzhiyun static bool cbr_test_2500(struct ast_private *ast)
1681*4882a593Smuzhiyun {
1682*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
1683*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
1684*4882a593Smuzhiyun 	if (!mmc_test_burst(ast, 0))
1685*4882a593Smuzhiyun 		return false;
1686*4882a593Smuzhiyun 	if (!mmc_test_single_2500(ast, 0))
1687*4882a593Smuzhiyun 		return false;
1688*4882a593Smuzhiyun 	return true;
1689*4882a593Smuzhiyun }
1690*4882a593Smuzhiyun 
ddr_test_2500(struct ast_private * ast)1691*4882a593Smuzhiyun static bool ddr_test_2500(struct ast_private *ast)
1692*4882a593Smuzhiyun {
1693*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
1694*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
1695*4882a593Smuzhiyun 	if (!mmc_test_burst(ast, 0))
1696*4882a593Smuzhiyun 		return false;
1697*4882a593Smuzhiyun 	if (!mmc_test_burst(ast, 1))
1698*4882a593Smuzhiyun 		return false;
1699*4882a593Smuzhiyun 	if (!mmc_test_burst(ast, 2))
1700*4882a593Smuzhiyun 		return false;
1701*4882a593Smuzhiyun 	if (!mmc_test_burst(ast, 3))
1702*4882a593Smuzhiyun 		return false;
1703*4882a593Smuzhiyun 	if (!mmc_test_single_2500(ast, 0))
1704*4882a593Smuzhiyun 		return false;
1705*4882a593Smuzhiyun 	return true;
1706*4882a593Smuzhiyun }
1707*4882a593Smuzhiyun 
ddr_init_common_2500(struct ast_private * ast)1708*4882a593Smuzhiyun static void ddr_init_common_2500(struct ast_private *ast)
1709*4882a593Smuzhiyun {
1710*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
1711*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0008, 0x2003000F);
1712*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0038, 0x00000FFF);
1713*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0040, 0x88448844);
1714*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0044, 0x24422288);
1715*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
1716*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E004C, 0x22222222);
1717*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1718*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0208, 0x00000000);
1719*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0218, 0x00000000);
1720*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0220, 0x00000000);
1721*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0228, 0x00000000);
1722*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0230, 0x00000000);
1723*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02A8, 0x00000000);
1724*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02B0, 0x00000000);
1725*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0240, 0x86000000);
1726*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0244, 0x00008600);
1727*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0248, 0x80000000);
1728*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E024C, 0x80808080);
1729*4882a593Smuzhiyun }
1730*4882a593Smuzhiyun 
ddr_phy_init_2500(struct ast_private * ast)1731*4882a593Smuzhiyun static void ddr_phy_init_2500(struct ast_private *ast)
1732*4882a593Smuzhiyun {
1733*4882a593Smuzhiyun 	u32 data, pass, timecnt;
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun 	pass = 0;
1736*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
1737*4882a593Smuzhiyun 	while (!pass) {
1738*4882a593Smuzhiyun 		for (timecnt = 0; timecnt < TIMEOUT; timecnt++) {
1739*4882a593Smuzhiyun 			data = ast_mindwm(ast, 0x1E6E0060) & 0x1;
1740*4882a593Smuzhiyun 			if (!data)
1741*4882a593Smuzhiyun 				break;
1742*4882a593Smuzhiyun 		}
1743*4882a593Smuzhiyun 		if (timecnt != TIMEOUT) {
1744*4882a593Smuzhiyun 			data = ast_mindwm(ast, 0x1E6E0300) & 0x000A0000;
1745*4882a593Smuzhiyun 			if (!data)
1746*4882a593Smuzhiyun 				pass = 1;
1747*4882a593Smuzhiyun 		}
1748*4882a593Smuzhiyun 		if (!pass) {
1749*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
1750*4882a593Smuzhiyun 			udelay(10); /* delay 10 us */
1751*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
1752*4882a593Smuzhiyun 		}
1753*4882a593Smuzhiyun 	}
1754*4882a593Smuzhiyun 
1755*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0060, 0x00000006);
1756*4882a593Smuzhiyun }
1757*4882a593Smuzhiyun 
1758*4882a593Smuzhiyun /*
1759*4882a593Smuzhiyun  * Check DRAM Size
1760*4882a593Smuzhiyun  * 1Gb : 0x80000000 ~ 0x87FFFFFF
1761*4882a593Smuzhiyun  * 2Gb : 0x80000000 ~ 0x8FFFFFFF
1762*4882a593Smuzhiyun  * 4Gb : 0x80000000 ~ 0x9FFFFFFF
1763*4882a593Smuzhiyun  * 8Gb : 0x80000000 ~ 0xBFFFFFFF
1764*4882a593Smuzhiyun  */
check_dram_size_2500(struct ast_private * ast,u32 tRFC)1765*4882a593Smuzhiyun static void check_dram_size_2500(struct ast_private *ast, u32 tRFC)
1766*4882a593Smuzhiyun {
1767*4882a593Smuzhiyun 	u32 reg_04, reg_14;
1768*4882a593Smuzhiyun 
1769*4882a593Smuzhiyun 	reg_04 = ast_mindwm(ast, 0x1E6E0004) & 0xfffffffc;
1770*4882a593Smuzhiyun 	reg_14 = ast_mindwm(ast, 0x1E6E0014) & 0xffffff00;
1771*4882a593Smuzhiyun 
1772*4882a593Smuzhiyun 	ast_moutdwm(ast, 0xA0100000, 0x41424344);
1773*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x90100000, 0x35363738);
1774*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x88100000, 0x292A2B2C);
1775*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x80100000, 0x1D1E1F10);
1776*4882a593Smuzhiyun 
1777*4882a593Smuzhiyun 	/* Check 8Gbit */
1778*4882a593Smuzhiyun 	if (ast_mindwm(ast, 0xA0100000) == 0x41424344) {
1779*4882a593Smuzhiyun 		reg_04 |= 0x03;
1780*4882a593Smuzhiyun 		reg_14 |= (tRFC >> 24) & 0xFF;
1781*4882a593Smuzhiyun 		/* Check 4Gbit */
1782*4882a593Smuzhiyun 	} else if (ast_mindwm(ast, 0x90100000) == 0x35363738) {
1783*4882a593Smuzhiyun 		reg_04 |= 0x02;
1784*4882a593Smuzhiyun 		reg_14 |= (tRFC >> 16) & 0xFF;
1785*4882a593Smuzhiyun 		/* Check 2Gbit */
1786*4882a593Smuzhiyun 	} else if (ast_mindwm(ast, 0x88100000) == 0x292A2B2C) {
1787*4882a593Smuzhiyun 		reg_04 |= 0x01;
1788*4882a593Smuzhiyun 		reg_14 |= (tRFC >> 8) & 0xFF;
1789*4882a593Smuzhiyun 	} else {
1790*4882a593Smuzhiyun 		reg_14 |= tRFC & 0xFF;
1791*4882a593Smuzhiyun 	}
1792*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0004, reg_04);
1793*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0014, reg_14);
1794*4882a593Smuzhiyun }
1795*4882a593Smuzhiyun 
enable_cache_2500(struct ast_private * ast)1796*4882a593Smuzhiyun static void enable_cache_2500(struct ast_private *ast)
1797*4882a593Smuzhiyun {
1798*4882a593Smuzhiyun 	u32 reg_04, data;
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun 	reg_04 = ast_mindwm(ast, 0x1E6E0004);
1801*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x1000);
1802*4882a593Smuzhiyun 
1803*4882a593Smuzhiyun 	do
1804*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E0004);
1805*4882a593Smuzhiyun 	while (!(data & 0x80000));
1806*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
1807*4882a593Smuzhiyun }
1808*4882a593Smuzhiyun 
set_mpll_2500(struct ast_private * ast)1809*4882a593Smuzhiyun static void set_mpll_2500(struct ast_private *ast)
1810*4882a593Smuzhiyun {
1811*4882a593Smuzhiyun 	u32 addr, data, param;
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun 	/* Reset MMC */
1814*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
1815*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
1816*4882a593Smuzhiyun 	for (addr = 0x1e6e0004; addr < 0x1e6e0090;) {
1817*4882a593Smuzhiyun 		ast_moutdwm(ast, addr, 0x0);
1818*4882a593Smuzhiyun 		addr += 4;
1819*4882a593Smuzhiyun 	}
1820*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x00020000);
1821*4882a593Smuzhiyun 
1822*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
1823*4882a593Smuzhiyun 	data = ast_mindwm(ast, 0x1E6E2070) & 0x00800000;
1824*4882a593Smuzhiyun 	if (data) {
1825*4882a593Smuzhiyun 		/* CLKIN = 25MHz */
1826*4882a593Smuzhiyun 		param = 0x930023E0;
1827*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E2160, 0x00011320);
1828*4882a593Smuzhiyun 	} else {
1829*4882a593Smuzhiyun 		/* CLKIN = 24MHz */
1830*4882a593Smuzhiyun 		param = 0x93002400;
1831*4882a593Smuzhiyun 	}
1832*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E2020, param);
1833*4882a593Smuzhiyun 	udelay(100);
1834*4882a593Smuzhiyun }
1835*4882a593Smuzhiyun 
reset_mmc_2500(struct ast_private * ast)1836*4882a593Smuzhiyun static void reset_mmc_2500(struct ast_private *ast)
1837*4882a593Smuzhiyun {
1838*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E78505C, 0x00000004);
1839*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E785044, 0x00000001);
1840*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E785048, 0x00004755);
1841*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E78504C, 0x00000013);
1842*4882a593Smuzhiyun 	mdelay(100);
1843*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E785054, 0x00000077);
1844*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
1845*4882a593Smuzhiyun }
1846*4882a593Smuzhiyun 
ddr3_init_2500(struct ast_private * ast,const u32 * ddr_table)1847*4882a593Smuzhiyun static void ddr3_init_2500(struct ast_private *ast, const u32 *ddr_table)
1848*4882a593Smuzhiyun {
1849*4882a593Smuzhiyun 
1850*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0004, 0x00000303);
1851*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
1852*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
1853*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
1854*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]);	     /* MODEREG4/6 */
1855*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]);	     /* MODEREG5 */
1856*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
1857*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]);	     /* MODEREG1/3 */
1858*4882a593Smuzhiyun 
1859*4882a593Smuzhiyun 	/* DDR PHY Setting */
1860*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0200, 0x02492AAE);
1861*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0204, 0x00001001);
1862*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
1863*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
1864*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
1865*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
1866*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
1867*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
1868*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
1869*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
1870*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
1871*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
1872*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
1873*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02C0, 0x00000006);
1874*4882a593Smuzhiyun 
1875*4882a593Smuzhiyun 	/* Controller Setting */
1876*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x00020091);
1877*4882a593Smuzhiyun 
1878*4882a593Smuzhiyun 	/* Wait DDR PHY init done */
1879*4882a593Smuzhiyun 	ddr_phy_init_2500(ast);
1880*4882a593Smuzhiyun 
1881*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
1882*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
1883*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
1884*4882a593Smuzhiyun 
1885*4882a593Smuzhiyun 	check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
1886*4882a593Smuzhiyun 	enable_cache_2500(ast);
1887*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
1888*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
1889*4882a593Smuzhiyun }
1890*4882a593Smuzhiyun 
ddr4_init_2500(struct ast_private * ast,const u32 * ddr_table)1891*4882a593Smuzhiyun static void ddr4_init_2500(struct ast_private *ast, const u32 *ddr_table)
1892*4882a593Smuzhiyun {
1893*4882a593Smuzhiyun 	u32 data, data2, pass, retrycnt;
1894*4882a593Smuzhiyun 	u32 ddr_vref, phy_vref;
1895*4882a593Smuzhiyun 	u32 min_ddr_vref = 0, min_phy_vref = 0;
1896*4882a593Smuzhiyun 	u32 max_ddr_vref = 0, max_phy_vref = 0;
1897*4882a593Smuzhiyun 
1898*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0004, 0x00000313);
1899*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
1900*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
1901*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
1902*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]);	     /* MODEREG4/6 */
1903*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]);	     /* MODEREG5 */
1904*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
1905*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]);	     /* MODEREG1/3 */
1906*4882a593Smuzhiyun 
1907*4882a593Smuzhiyun 	/* DDR PHY Setting */
1908*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0200, 0x42492AAE);
1909*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0204, 0x09002000);
1910*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
1911*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
1912*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
1913*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
1914*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
1915*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
1916*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
1917*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
1918*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
1919*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
1920*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
1921*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02C4, 0x3C183C3C);
1922*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02C8, 0x00631E0E);
1923*4882a593Smuzhiyun 
1924*4882a593Smuzhiyun 	/* Controller Setting */
1925*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x0001A991);
1926*4882a593Smuzhiyun 
1927*4882a593Smuzhiyun 	/* Train PHY Vref first */
1928*4882a593Smuzhiyun 	pass = 0;
1929*4882a593Smuzhiyun 
1930*4882a593Smuzhiyun 	for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
1931*4882a593Smuzhiyun 		max_phy_vref = 0x0;
1932*4882a593Smuzhiyun 		pass = 0;
1933*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1E6E02C0, 0x00001C06);
1934*4882a593Smuzhiyun 		for (phy_vref = 0x40; phy_vref < 0x80; phy_vref++) {
1935*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1936*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
1937*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E02CC, phy_vref | (phy_vref << 8));
1938*4882a593Smuzhiyun 			/* Fire DFI Init */
1939*4882a593Smuzhiyun 			ddr_phy_init_2500(ast);
1940*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
1941*4882a593Smuzhiyun 			if (cbr_test_2500(ast)) {
1942*4882a593Smuzhiyun 				pass++;
1943*4882a593Smuzhiyun 				data = ast_mindwm(ast, 0x1E6E03D0);
1944*4882a593Smuzhiyun 				data2 = data >> 8;
1945*4882a593Smuzhiyun 				data  = data & 0xff;
1946*4882a593Smuzhiyun 				if (data > data2)
1947*4882a593Smuzhiyun 					data = data2;
1948*4882a593Smuzhiyun 				if (max_phy_vref < data) {
1949*4882a593Smuzhiyun 					max_phy_vref = data;
1950*4882a593Smuzhiyun 					min_phy_vref = phy_vref;
1951*4882a593Smuzhiyun 				}
1952*4882a593Smuzhiyun 			} else if (pass > 0)
1953*4882a593Smuzhiyun 				break;
1954*4882a593Smuzhiyun 		}
1955*4882a593Smuzhiyun 	}
1956*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02CC, min_phy_vref | (min_phy_vref << 8));
1957*4882a593Smuzhiyun 
1958*4882a593Smuzhiyun 	/* Train DDR Vref next */
1959*4882a593Smuzhiyun 	pass = 0;
1960*4882a593Smuzhiyun 
1961*4882a593Smuzhiyun 	for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
1962*4882a593Smuzhiyun 		min_ddr_vref = 0xFF;
1963*4882a593Smuzhiyun 		max_ddr_vref = 0x0;
1964*4882a593Smuzhiyun 		pass = 0;
1965*4882a593Smuzhiyun 		for (ddr_vref = 0x00; ddr_vref < 0x40; ddr_vref++) {
1966*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1967*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
1968*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
1969*4882a593Smuzhiyun 			/* Fire DFI Init */
1970*4882a593Smuzhiyun 			ddr_phy_init_2500(ast);
1971*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
1972*4882a593Smuzhiyun 			if (cbr_test_2500(ast)) {
1973*4882a593Smuzhiyun 				pass++;
1974*4882a593Smuzhiyun 				if (min_ddr_vref > ddr_vref)
1975*4882a593Smuzhiyun 					min_ddr_vref = ddr_vref;
1976*4882a593Smuzhiyun 				if (max_ddr_vref < ddr_vref)
1977*4882a593Smuzhiyun 					max_ddr_vref = ddr_vref;
1978*4882a593Smuzhiyun 			} else if (pass != 0)
1979*4882a593Smuzhiyun 				break;
1980*4882a593Smuzhiyun 		}
1981*4882a593Smuzhiyun 	}
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1984*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
1985*4882a593Smuzhiyun 	ddr_vref = (min_ddr_vref + max_ddr_vref + 1) >> 1;
1986*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
1987*4882a593Smuzhiyun 
1988*4882a593Smuzhiyun 	/* Wait DDR PHY init done */
1989*4882a593Smuzhiyun 	ddr_phy_init_2500(ast);
1990*4882a593Smuzhiyun 
1991*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
1992*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
1993*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
1994*4882a593Smuzhiyun 
1995*4882a593Smuzhiyun 	check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
1996*4882a593Smuzhiyun 	enable_cache_2500(ast);
1997*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
1998*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
1999*4882a593Smuzhiyun }
2000*4882a593Smuzhiyun 
ast_dram_init_2500(struct ast_private * ast)2001*4882a593Smuzhiyun static bool ast_dram_init_2500(struct ast_private *ast)
2002*4882a593Smuzhiyun {
2003*4882a593Smuzhiyun 	u32 data;
2004*4882a593Smuzhiyun 	u32 max_tries = 5;
2005*4882a593Smuzhiyun 
2006*4882a593Smuzhiyun 	do {
2007*4882a593Smuzhiyun 		if (max_tries-- == 0)
2008*4882a593Smuzhiyun 			return false;
2009*4882a593Smuzhiyun 		set_mpll_2500(ast);
2010*4882a593Smuzhiyun 		reset_mmc_2500(ast);
2011*4882a593Smuzhiyun 		ddr_init_common_2500(ast);
2012*4882a593Smuzhiyun 
2013*4882a593Smuzhiyun 		data = ast_mindwm(ast, 0x1E6E2070);
2014*4882a593Smuzhiyun 		if (data & 0x01000000)
2015*4882a593Smuzhiyun 			ddr4_init_2500(ast, ast2500_ddr4_1600_timing_table);
2016*4882a593Smuzhiyun 		else
2017*4882a593Smuzhiyun 			ddr3_init_2500(ast, ast2500_ddr3_1600_timing_table);
2018*4882a593Smuzhiyun 	} while (!ddr_test_2500(ast));
2019*4882a593Smuzhiyun 
2020*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E2040, ast_mindwm(ast, 0x1E6E2040) | 0x41);
2021*4882a593Smuzhiyun 
2022*4882a593Smuzhiyun 	/* Patch code */
2023*4882a593Smuzhiyun 	data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
2024*4882a593Smuzhiyun 	ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
2025*4882a593Smuzhiyun 
2026*4882a593Smuzhiyun 	return true;
2027*4882a593Smuzhiyun }
2028*4882a593Smuzhiyun 
ast_post_chip_2500(struct drm_device * dev)2029*4882a593Smuzhiyun void ast_post_chip_2500(struct drm_device *dev)
2030*4882a593Smuzhiyun {
2031*4882a593Smuzhiyun 	struct ast_private *ast = to_ast_private(dev);
2032*4882a593Smuzhiyun 	u32 temp;
2033*4882a593Smuzhiyun 	u8 reg;
2034*4882a593Smuzhiyun 
2035*4882a593Smuzhiyun 	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
2036*4882a593Smuzhiyun 	if ((reg & 0x80) == 0) {/* vga only */
2037*4882a593Smuzhiyun 		/* Clear bus lock condition */
2038*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e600000, 0xAEED1A03);
2039*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e600084, 0x00010000);
2040*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e600088, 0x00000000);
2041*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
2042*4882a593Smuzhiyun 		ast_write32(ast, 0xf004, 0x1e6e0000);
2043*4882a593Smuzhiyun 		ast_write32(ast, 0xf000, 0x1);
2044*4882a593Smuzhiyun 		ast_write32(ast, 0x12000, 0x1688a8a8);
2045*4882a593Smuzhiyun 		while (ast_read32(ast, 0x12000) != 0x1)
2046*4882a593Smuzhiyun 			;
2047*4882a593Smuzhiyun 
2048*4882a593Smuzhiyun 		ast_write32(ast, 0x10000, 0xfc600309);
2049*4882a593Smuzhiyun 		while (ast_read32(ast, 0x10000) != 0x1)
2050*4882a593Smuzhiyun 			;
2051*4882a593Smuzhiyun 
2052*4882a593Smuzhiyun 		/* Slow down CPU/AHB CLK in VGA only mode */
2053*4882a593Smuzhiyun 		temp = ast_read32(ast, 0x12008);
2054*4882a593Smuzhiyun 		temp |= 0x73;
2055*4882a593Smuzhiyun 		ast_write32(ast, 0x12008, temp);
2056*4882a593Smuzhiyun 
2057*4882a593Smuzhiyun 		/* Reset USB port to patch USB unknown device issue */
2058*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e2090, 0x20000000);
2059*4882a593Smuzhiyun 		temp  = ast_mindwm(ast, 0x1e6e2094);
2060*4882a593Smuzhiyun 		temp |= 0x00004000;
2061*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e2094, temp);
2062*4882a593Smuzhiyun 		temp  = ast_mindwm(ast, 0x1e6e2070);
2063*4882a593Smuzhiyun 		if (temp & 0x00800000) {
2064*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1e6e207c, 0x00800000);
2065*4882a593Smuzhiyun 			mdelay(100);
2066*4882a593Smuzhiyun 			ast_moutdwm(ast, 0x1e6e2070, 0x00800000);
2067*4882a593Smuzhiyun 		}
2068*4882a593Smuzhiyun 
2069*4882a593Smuzhiyun 		if (!ast_dram_init_2500(ast))
2070*4882a593Smuzhiyun 			drm_err(dev, "DRAM init failed !\n");
2071*4882a593Smuzhiyun 
2072*4882a593Smuzhiyun 		temp = ast_mindwm(ast, 0x1e6e2040);
2073*4882a593Smuzhiyun 		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
2074*4882a593Smuzhiyun 	}
2075*4882a593Smuzhiyun 
2076*4882a593Smuzhiyun 	/* wait ready */
2077*4882a593Smuzhiyun 	do {
2078*4882a593Smuzhiyun 		reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
2079*4882a593Smuzhiyun 	} while ((reg & 0x40) == 0);
2080*4882a593Smuzhiyun }
2081