xref: /openbmc/linux/drivers/gpu/drm/ast/ast_post.c (revision ecf64579)
1312fec14SDave Airlie /*
2312fec14SDave Airlie  * Copyright 2012 Red Hat Inc.
3312fec14SDave Airlie  *
4312fec14SDave Airlie  * Permission is hereby granted, free of charge, to any person obtaining a
5312fec14SDave Airlie  * copy of this software and associated documentation files (the
6312fec14SDave Airlie  * "Software"), to deal in the Software without restriction, including
7312fec14SDave Airlie  * without limitation the rights to use, copy, modify, merge, publish,
8312fec14SDave Airlie  * distribute, sub license, and/or sell copies of the Software, and to
9312fec14SDave Airlie  * permit persons to whom the Software is furnished to do so, subject to
10312fec14SDave Airlie  * the following conditions:
11312fec14SDave Airlie  *
12312fec14SDave Airlie  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13312fec14SDave Airlie  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14312fec14SDave Airlie  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15312fec14SDave Airlie  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16312fec14SDave Airlie  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17312fec14SDave Airlie  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18312fec14SDave Airlie  * USE OR OTHER DEALINGS IN THE SOFTWARE.
19312fec14SDave Airlie  *
20312fec14SDave Airlie  * The above copyright notice and this permission notice (including the
21312fec14SDave Airlie  * next paragraph) shall be included in all copies or substantial portions
22312fec14SDave Airlie  * of the Software.
23312fec14SDave Airlie  *
24312fec14SDave Airlie  */
25312fec14SDave Airlie /*
26312fec14SDave Airlie  * Authors: Dave Airlie <airlied@redhat.com>
27312fec14SDave Airlie  */
28312fec14SDave Airlie 
29fbbbd160SSam Ravnborg #include <linux/delay.h>
30fbbbd160SSam Ravnborg #include <linux/pci.h>
31fbbbd160SSam Ravnborg 
32fbbbd160SSam Ravnborg #include <drm/drm_print.h>
33312fec14SDave Airlie 
34312fec14SDave Airlie #include "ast_dram_tables.h"
35fbbbd160SSam Ravnborg #include "ast_drv.h"
36312fec14SDave Airlie 
37d95618efSBenjamin Herrenschmidt static void ast_post_chip_2300(struct drm_device *dev);
3894fdc2a8SY.C. Chen static void ast_post_chip_2500(struct drm_device *dev);
39312fec14SDave Airlie 
40312fec14SDave Airlie static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
41312fec14SDave Airlie static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff };
42312fec14SDave Airlie 
43312fec14SDave Airlie static void
ast_set_def_ext_reg(struct drm_device * dev)44312fec14SDave Airlie ast_set_def_ext_reg(struct drm_device *dev)
45312fec14SDave Airlie {
465abaa683SThomas Zimmermann 	struct ast_device *ast = to_ast_device(dev);
47312fec14SDave Airlie 	u8 i, index, reg;
48312fec14SDave Airlie 	const u8 *ext_reg_info;
49312fec14SDave Airlie 
50312fec14SDave Airlie 	/* reset scratch */
51bad09da6SY.C. Chen 	for (i = 0x81; i <= 0x9f; i++)
52312fec14SDave Airlie 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
53312fec14SDave Airlie 
54*ecf64579SThomas Zimmermann 	if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast))
55312fec14SDave Airlie 		ext_reg_info = extreginfo_ast2300;
56312fec14SDave Airlie 	else
57312fec14SDave Airlie 		ext_reg_info = extreginfo;
58312fec14SDave Airlie 
59312fec14SDave Airlie 	index = 0xa0;
60312fec14SDave Airlie 	while (*ext_reg_info != 0xff) {
61312fec14SDave Airlie 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info);
62312fec14SDave Airlie 		index++;
63312fec14SDave Airlie 		ext_reg_info++;
64312fec14SDave Airlie 	}
65312fec14SDave Airlie 
66312fec14SDave Airlie 	/* disable standard IO/MEM decode if secondary */
67312fec14SDave Airlie 	/* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */
68312fec14SDave Airlie 
69312fec14SDave Airlie 	/* Set Ext. Default */
70312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01);
71312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00);
72312fec14SDave Airlie 
73312fec14SDave Airlie 	/* Enable RAMDAC for A1 */
74312fec14SDave Airlie 	reg = 0x04;
75*ecf64579SThomas Zimmermann 	if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast))
76312fec14SDave Airlie 		reg |= 0x20;
77312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
78312fec14SDave Airlie }
79312fec14SDave Airlie 
ast_mindwm(struct ast_device * ast,u32 r)8037b42cf9SThomas Zimmermann u32 ast_mindwm(struct ast_device *ast, u32 r)
81312fec14SDave Airlie {
82318cfa29SDave Airlie 	uint32_t data;
83318cfa29SDave Airlie 
84312fec14SDave Airlie 	ast_write32(ast, 0xf004, r & 0xffff0000);
85312fec14SDave Airlie 	ast_write32(ast, 0xf000, 0x1);
86312fec14SDave Airlie 
87318cfa29SDave Airlie 	do {
88318cfa29SDave Airlie 		data = ast_read32(ast, 0xf004) & 0xffff0000;
89318cfa29SDave Airlie 	} while (data != (r & 0xffff0000));
90312fec14SDave Airlie 	return ast_read32(ast, 0x10000 + (r & 0x0000ffff));
91312fec14SDave Airlie }
92312fec14SDave Airlie 
ast_moutdwm(struct ast_device * ast,u32 r,u32 v)9337b42cf9SThomas Zimmermann void ast_moutdwm(struct ast_device *ast, u32 r, u32 v)
94312fec14SDave Airlie {
95318cfa29SDave Airlie 	uint32_t data;
96312fec14SDave Airlie 	ast_write32(ast, 0xf004, r & 0xffff0000);
97312fec14SDave Airlie 	ast_write32(ast, 0xf000, 0x1);
98318cfa29SDave Airlie 	do {
99318cfa29SDave Airlie 		data = ast_read32(ast, 0xf004) & 0xffff0000;
100318cfa29SDave Airlie 	} while (data != (r & 0xffff0000));
101312fec14SDave Airlie 	ast_write32(ast, 0x10000 + (r & 0x0000ffff), v);
102312fec14SDave Airlie }
103312fec14SDave Airlie 
104312fec14SDave Airlie /*
105312fec14SDave Airlie  * AST2100/2150 DLL CBR Setting
106312fec14SDave Airlie  */
107312fec14SDave Airlie #define CBR_SIZE_AST2150	     ((16 << 10) - 1)
108312fec14SDave Airlie #define CBR_PASSNUM_AST2150          5
109312fec14SDave Airlie #define CBR_THRESHOLD_AST2150        10
110312fec14SDave Airlie #define CBR_THRESHOLD2_AST2150       10
111312fec14SDave Airlie #define TIMEOUT_AST2150              5000000
112312fec14SDave Airlie 
113312fec14SDave Airlie #define CBR_PATNUM_AST2150           8
114312fec14SDave Airlie 
115312fec14SDave Airlie static const u32 pattern_AST2150[14] = {
116312fec14SDave Airlie 	0xFF00FF00,
117312fec14SDave Airlie 	0xCC33CC33,
118312fec14SDave Airlie 	0xAA55AA55,
119312fec14SDave Airlie 	0xFFFE0001,
120312fec14SDave Airlie 	0x683501FE,
121312fec14SDave Airlie 	0x0F1929B0,
122312fec14SDave Airlie 	0x2D0B4346,
123312fec14SDave Airlie 	0x60767F02,
124312fec14SDave Airlie 	0x6FBE36A6,
125312fec14SDave Airlie 	0x3A253035,
126312fec14SDave Airlie 	0x3019686D,
127312fec14SDave Airlie 	0x41C6167E,
128312fec14SDave Airlie 	0x620152BF,
129312fec14SDave Airlie 	0x20F050E0
130312fec14SDave Airlie };
131312fec14SDave Airlie 
mmctestburst2_ast2150(struct ast_device * ast,u32 datagen)13237b42cf9SThomas Zimmermann static u32 mmctestburst2_ast2150(struct ast_device *ast, u32 datagen)
133312fec14SDave Airlie {
134312fec14SDave Airlie 	u32 data, timeout;
135312fec14SDave Airlie 
1360e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1370e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3));
138312fec14SDave Airlie 	timeout = 0;
139312fec14SDave Airlie 	do {
1400e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
141312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
1420e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
143312fec14SDave Airlie 			return 0xffffffff;
144312fec14SDave Airlie 		}
145312fec14SDave Airlie 	} while (!data);
1460e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1470e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3));
148312fec14SDave Airlie 	timeout = 0;
149312fec14SDave Airlie 	do {
1500e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
151312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
1520e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
153312fec14SDave Airlie 			return 0xffffffff;
154312fec14SDave Airlie 		}
155312fec14SDave Airlie 	} while (!data);
1560e5ce924SDave Airlie 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
1570e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
158312fec14SDave Airlie 	return data;
159312fec14SDave Airlie }
160312fec14SDave Airlie 
161312fec14SDave Airlie #if 0 /* unused in DDX driver - here for completeness */
16237b42cf9SThomas Zimmermann static u32 mmctestsingle2_ast2150(struct ast_device *ast, u32 datagen)
163312fec14SDave Airlie {
164312fec14SDave Airlie 	u32 data, timeout;
165312fec14SDave Airlie 
1660e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1670e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
168312fec14SDave Airlie 	timeout = 0;
169312fec14SDave Airlie 	do {
1700e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
171312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
1720e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
173312fec14SDave Airlie 			return 0xffffffff;
174312fec14SDave Airlie 		}
175312fec14SDave Airlie 	} while (!data);
1760e5ce924SDave Airlie 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
1770e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
178312fec14SDave Airlie 	return data;
179312fec14SDave Airlie }
180312fec14SDave Airlie #endif
181312fec14SDave Airlie 
cbrtest_ast2150(struct ast_device * ast)18237b42cf9SThomas Zimmermann static int cbrtest_ast2150(struct ast_device *ast)
183312fec14SDave Airlie {
184312fec14SDave Airlie 	int i;
185312fec14SDave Airlie 
186312fec14SDave Airlie 	for (i = 0; i < 8; i++)
187312fec14SDave Airlie 		if (mmctestburst2_ast2150(ast, i))
188312fec14SDave Airlie 			return 0;
189312fec14SDave Airlie 	return 1;
190312fec14SDave Airlie }
191312fec14SDave Airlie 
cbrscan_ast2150(struct ast_device * ast,int busw)19237b42cf9SThomas Zimmermann static int cbrscan_ast2150(struct ast_device *ast, int busw)
193312fec14SDave Airlie {
194312fec14SDave Airlie 	u32 patcnt, loop;
195312fec14SDave Airlie 
196312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) {
1970e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]);
198312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) {
199312fec14SDave Airlie 			if (cbrtest_ast2150(ast))
200312fec14SDave Airlie 				break;
201312fec14SDave Airlie 		}
202312fec14SDave Airlie 		if (loop == CBR_PASSNUM_AST2150)
203312fec14SDave Airlie 			return 0;
204312fec14SDave Airlie 	}
205312fec14SDave Airlie 	return 1;
206312fec14SDave Airlie }
207312fec14SDave Airlie 
208312fec14SDave Airlie 
cbrdlli_ast2150(struct ast_device * ast,int busw)20937b42cf9SThomas Zimmermann static void cbrdlli_ast2150(struct ast_device *ast, int busw)
210312fec14SDave Airlie {
211312fec14SDave Airlie 	u32 dll_min[4], dll_max[4], dlli, data, passcnt;
212312fec14SDave Airlie 
213312fec14SDave Airlie cbr_start:
214312fec14SDave Airlie 	dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff;
215312fec14SDave Airlie 	dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0;
216312fec14SDave Airlie 	passcnt = 0;
217312fec14SDave Airlie 
218312fec14SDave Airlie 	for (dlli = 0; dlli < 100; dlli++) {
2190e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
220312fec14SDave Airlie 		data = cbrscan_ast2150(ast, busw);
221312fec14SDave Airlie 		if (data != 0) {
222312fec14SDave Airlie 			if (data & 0x1) {
223312fec14SDave Airlie 				if (dll_min[0] > dlli)
224312fec14SDave Airlie 					dll_min[0] = dlli;
225312fec14SDave Airlie 				if (dll_max[0] < dlli)
226312fec14SDave Airlie 					dll_max[0] = dlli;
227312fec14SDave Airlie 			}
228312fec14SDave Airlie 			passcnt++;
229312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD_AST2150)
230312fec14SDave Airlie 			goto cbr_start;
231312fec14SDave Airlie 	}
232312fec14SDave Airlie 	if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150)
233312fec14SDave Airlie 		goto cbr_start;
234312fec14SDave Airlie 
235312fec14SDave Airlie 	dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4);
2360e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
237312fec14SDave Airlie }
238312fec14SDave Airlie 
239312fec14SDave Airlie 
240312fec14SDave Airlie 
ast_init_dram_reg(struct drm_device * dev)241312fec14SDave Airlie static void ast_init_dram_reg(struct drm_device *dev)
242312fec14SDave Airlie {
2435abaa683SThomas Zimmermann 	struct ast_device *ast = to_ast_device(dev);
244312fec14SDave Airlie 	u8 j;
245312fec14SDave Airlie 	u32 data, temp, i;
246312fec14SDave Airlie 	const struct ast_dramstruct *dram_reg_info;
247312fec14SDave Airlie 
248312fec14SDave Airlie 	j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
249312fec14SDave Airlie 
250312fec14SDave Airlie 	if ((j & 0x80) == 0) { /* VGA only */
251*ecf64579SThomas Zimmermann 		if (IS_AST_GEN1(ast)) {
252312fec14SDave Airlie 			dram_reg_info = ast2000_dram_table_data;
253312fec14SDave Airlie 			ast_write32(ast, 0xf004, 0x1e6e0000);
254312fec14SDave Airlie 			ast_write32(ast, 0xf000, 0x1);
255312fec14SDave Airlie 			ast_write32(ast, 0x10100, 0xa8);
256312fec14SDave Airlie 
257312fec14SDave Airlie 			do {
258312fec14SDave Airlie 				;
259312fec14SDave Airlie 			} while (ast_read32(ast, 0x10100) != 0xa8);
260*ecf64579SThomas Zimmermann 		} else { /* GEN2/GEN3 */
2614cfe75f0SThomas Zimmermann 			if (ast->chip == AST2100 || ast->chip == AST2200)
262312fec14SDave Airlie 				dram_reg_info = ast2100_dram_table_data;
263312fec14SDave Airlie 			else
264312fec14SDave Airlie 				dram_reg_info = ast1100_dram_table_data;
265312fec14SDave Airlie 
266312fec14SDave Airlie 			ast_write32(ast, 0xf004, 0x1e6e0000);
267312fec14SDave Airlie 			ast_write32(ast, 0xf000, 0x1);
268312fec14SDave Airlie 			ast_write32(ast, 0x12000, 0x1688A8A8);
269312fec14SDave Airlie 			do {
270312fec14SDave Airlie 				;
271312fec14SDave Airlie 			} while (ast_read32(ast, 0x12000) != 0x01);
272312fec14SDave Airlie 
273312fec14SDave Airlie 			ast_write32(ast, 0x10000, 0xfc600309);
274312fec14SDave Airlie 			do {
275312fec14SDave Airlie 				;
276312fec14SDave Airlie 			} while (ast_read32(ast, 0x10000) != 0x01);
277312fec14SDave Airlie 		}
278312fec14SDave Airlie 
279312fec14SDave Airlie 		while (dram_reg_info->index != 0xffff) {
280312fec14SDave Airlie 			if (dram_reg_info->index == 0xff00) {/* delay fn */
281312fec14SDave Airlie 				for (i = 0; i < 15; i++)
282312fec14SDave Airlie 					udelay(dram_reg_info->data);
283*ecf64579SThomas Zimmermann 			} else if (dram_reg_info->index == 0x4 && !IS_AST_GEN1(ast)) {
284312fec14SDave Airlie 				data = dram_reg_info->data;
285312fec14SDave Airlie 				if (ast->dram_type == AST_DRAM_1Gx16)
286312fec14SDave Airlie 					data = 0x00000d89;
287312fec14SDave Airlie 				else if (ast->dram_type == AST_DRAM_1Gx32)
288312fec14SDave Airlie 					data = 0x00000c8d;
289312fec14SDave Airlie 
290312fec14SDave Airlie 				temp = ast_read32(ast, 0x12070);
291312fec14SDave Airlie 				temp &= 0xc;
292312fec14SDave Airlie 				temp <<= 2;
293312fec14SDave Airlie 				ast_write32(ast, 0x10000 + dram_reg_info->index, data | temp);
294312fec14SDave Airlie 			} else
295312fec14SDave Airlie 				ast_write32(ast, 0x10000 + dram_reg_info->index, dram_reg_info->data);
296312fec14SDave Airlie 			dram_reg_info++;
297312fec14SDave Airlie 		}
298312fec14SDave Airlie 
299312fec14SDave Airlie 		/* AST 2100/2150 DRAM calibration */
300312fec14SDave Airlie 		data = ast_read32(ast, 0x10120);
301312fec14SDave Airlie 		if (data == 0x5061) { /* 266Mhz */
302312fec14SDave Airlie 			data = ast_read32(ast, 0x10004);
303312fec14SDave Airlie 			if (data & 0x40)
304312fec14SDave Airlie 				cbrdlli_ast2150(ast, 16); /* 16 bits */
305312fec14SDave Airlie 			else
306312fec14SDave Airlie 				cbrdlli_ast2150(ast, 32); /* 32 bits */
307312fec14SDave Airlie 		}
308312fec14SDave Airlie 
309*ecf64579SThomas Zimmermann 		switch (AST_GEN(ast)) {
310*ecf64579SThomas Zimmermann 		case 1:
311312fec14SDave Airlie 			temp = ast_read32(ast, 0x10140);
312312fec14SDave Airlie 			ast_write32(ast, 0x10140, temp | 0x40);
313312fec14SDave Airlie 			break;
314*ecf64579SThomas Zimmermann 		case 2:
315*ecf64579SThomas Zimmermann 		case 3:
316312fec14SDave Airlie 			temp = ast_read32(ast, 0x1200c);
317312fec14SDave Airlie 			ast_write32(ast, 0x1200c, temp & 0xfffffffd);
318312fec14SDave Airlie 			temp = ast_read32(ast, 0x12040);
319312fec14SDave Airlie 			ast_write32(ast, 0x12040, temp | 0x40);
320312fec14SDave Airlie 			break;
321312fec14SDave Airlie 		default:
322312fec14SDave Airlie 			break;
323312fec14SDave Airlie 		}
324312fec14SDave Airlie 	}
325312fec14SDave Airlie 
326312fec14SDave Airlie 	/* wait ready */
327312fec14SDave Airlie 	do {
328312fec14SDave Airlie 		j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
329312fec14SDave Airlie 	} while ((j & 0x40) == 0);
330312fec14SDave Airlie }
331312fec14SDave Airlie 
ast_post_gpu(struct drm_device * dev)332312fec14SDave Airlie void ast_post_gpu(struct drm_device *dev)
333312fec14SDave Airlie {
3345abaa683SThomas Zimmermann 	struct ast_device *ast = to_ast_device(dev);
335312fec14SDave Airlie 
336312fec14SDave Airlie 	ast_set_def_ext_reg(dev);
337312fec14SDave Airlie 
338*ecf64579SThomas Zimmermann 	if (IS_AST_GEN7(ast)) {
339bed61c8fSJammy Huang 		if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
340bed61c8fSJammy Huang 			ast_dp_launch(dev);
341594e9c04SKuoHsiang Chou 	} else if (ast->config_mode == ast_use_p2a) {
342*ecf64579SThomas Zimmermann 		if (IS_AST_GEN6(ast))
34394fdc2a8SY.C. Chen 			ast_post_chip_2500(dev);
344*ecf64579SThomas Zimmermann 		else if (IS_AST_GEN5(ast) || IS_AST_GEN4(ast))
345d95618efSBenjamin Herrenschmidt 			ast_post_chip_2300(dev);
346312fec14SDave Airlie 		else
347312fec14SDave Airlie 			ast_init_dram_reg(dev);
34883c6620bSDave Airlie 
34983c6620bSDave Airlie 		ast_init_3rdtx(dev);
35071f677a9SRussell Currey 	} else {
3517f35680aSThomas Zimmermann 		if (ast->tx_chip_types & AST_TX_SIL164_BIT)
3526c971c09SY.C. Chen 			ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);	/* Enable DVO */
3536c971c09SY.C. Chen 	}
3546c971c09SY.C. Chen }
355312fec14SDave Airlie 
356312fec14SDave Airlie /* AST 2300 DRAM settings */
357312fec14SDave Airlie #define AST_DDR3 0
358312fec14SDave Airlie #define AST_DDR2 1
359312fec14SDave Airlie 
360312fec14SDave Airlie struct ast2300_dram_param {
361312fec14SDave Airlie 	u32 dram_type;
362312fec14SDave Airlie 	u32 dram_chipid;
363312fec14SDave Airlie 	u32 dram_freq;
364312fec14SDave Airlie 	u32 vram_size;
365312fec14SDave Airlie 	u32 odt;
366312fec14SDave Airlie 	u32 wodt;
367312fec14SDave Airlie 	u32 rodt;
368312fec14SDave Airlie 	u32 dram_config;
369312fec14SDave Airlie 	u32 reg_PERIOD;
370312fec14SDave Airlie 	u32 reg_MADJ;
371312fec14SDave Airlie 	u32 reg_SADJ;
372312fec14SDave Airlie 	u32 reg_MRS;
373312fec14SDave Airlie 	u32 reg_EMRS;
374312fec14SDave Airlie 	u32 reg_AC1;
375312fec14SDave Airlie 	u32 reg_AC2;
376312fec14SDave Airlie 	u32 reg_DQSIC;
377312fec14SDave Airlie 	u32 reg_DRV;
378312fec14SDave Airlie 	u32 reg_IOZ;
379312fec14SDave Airlie 	u32 reg_DQIDLY;
380312fec14SDave Airlie 	u32 reg_FREQ;
381312fec14SDave Airlie 	u32 madj_max;
382312fec14SDave Airlie 	u32 dll2_finetune_step;
383312fec14SDave Airlie };
384312fec14SDave Airlie 
385312fec14SDave Airlie /*
386312fec14SDave Airlie  * DQSI DLL CBR Setting
387312fec14SDave Airlie  */
388318cfa29SDave Airlie #define CBR_SIZE0            ((1  << 10) - 1)
389312fec14SDave Airlie #define CBR_SIZE1            ((4  << 10) - 1)
390312fec14SDave Airlie #define CBR_SIZE2            ((64 << 10) - 1)
391312fec14SDave Airlie #define CBR_PASSNUM          5
392312fec14SDave Airlie #define CBR_PASSNUM2         5
393312fec14SDave Airlie #define CBR_THRESHOLD        10
394312fec14SDave Airlie #define CBR_THRESHOLD2       10
395312fec14SDave Airlie #define TIMEOUT              5000000
396312fec14SDave Airlie #define CBR_PATNUM           8
397312fec14SDave Airlie 
398312fec14SDave Airlie static const u32 pattern[8] = {
399312fec14SDave Airlie 	0xFF00FF00,
400312fec14SDave Airlie 	0xCC33CC33,
401312fec14SDave Airlie 	0xAA55AA55,
402312fec14SDave Airlie 	0x88778877,
403312fec14SDave Airlie 	0x92CC4D6E,
404312fec14SDave Airlie 	0x543D3CDE,
405312fec14SDave Airlie 	0xF1E843C7,
406312fec14SDave Airlie 	0x7C61D253
407312fec14SDave Airlie };
408312fec14SDave Airlie 
mmc_test(struct ast_device * ast,u32 datagen,u8 test_ctl)40937b42cf9SThomas Zimmermann static bool mmc_test(struct ast_device *ast, u32 datagen, u8 test_ctl)
410312fec14SDave Airlie {
411312fec14SDave Airlie 	u32 data, timeout;
412312fec14SDave Airlie 
4130e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
414b368e53aSBenjamin Herrenschmidt 	ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
415312fec14SDave Airlie 	timeout = 0;
416312fec14SDave Airlie 	do {
4170e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
418312fec14SDave Airlie 		if (data & 0x2000)
419b368e53aSBenjamin Herrenschmidt 			return false;
420312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
421b368e53aSBenjamin Herrenschmidt 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
422b368e53aSBenjamin Herrenschmidt 			return false;
423312fec14SDave Airlie 		}
424312fec14SDave Airlie 	} while (!data);
4250e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
426b368e53aSBenjamin Herrenschmidt 	return true;
427312fec14SDave Airlie }
428312fec14SDave Airlie 
mmc_test2(struct ast_device * ast,u32 datagen,u8 test_ctl)42937b42cf9SThomas Zimmermann static u32 mmc_test2(struct ast_device *ast, u32 datagen, u8 test_ctl)
430312fec14SDave Airlie {
431312fec14SDave Airlie 	u32 data, timeout;
432312fec14SDave Airlie 
4330e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
434b368e53aSBenjamin Herrenschmidt 	ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
435312fec14SDave Airlie 	timeout = 0;
436312fec14SDave Airlie 	do {
4370e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
438312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
4390e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
440b368e53aSBenjamin Herrenschmidt 			return 0xffffffff;
441312fec14SDave Airlie 		}
442312fec14SDave Airlie 	} while (!data);
4430e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1e6e0078);
444312fec14SDave Airlie 	data = (data | (data >> 16)) & 0xffff;
445b368e53aSBenjamin Herrenschmidt 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
446312fec14SDave Airlie 	return data;
447312fec14SDave Airlie }
448312fec14SDave Airlie 
449b368e53aSBenjamin Herrenschmidt 
mmc_test_burst(struct ast_device * ast,u32 datagen)45037b42cf9SThomas Zimmermann static bool mmc_test_burst(struct ast_device *ast, u32 datagen)
451b368e53aSBenjamin Herrenschmidt {
452b368e53aSBenjamin Herrenschmidt 	return mmc_test(ast, datagen, 0xc1);
453b368e53aSBenjamin Herrenschmidt }
454b368e53aSBenjamin Herrenschmidt 
mmc_test_burst2(struct ast_device * ast,u32 datagen)45537b42cf9SThomas Zimmermann static u32 mmc_test_burst2(struct ast_device *ast, u32 datagen)
456b368e53aSBenjamin Herrenschmidt {
457b368e53aSBenjamin Herrenschmidt 	return mmc_test2(ast, datagen, 0x41);
458b368e53aSBenjamin Herrenschmidt }
459b368e53aSBenjamin Herrenschmidt 
mmc_test_single(struct ast_device * ast,u32 datagen)46037b42cf9SThomas Zimmermann static bool mmc_test_single(struct ast_device *ast, u32 datagen)
461b368e53aSBenjamin Herrenschmidt {
462b368e53aSBenjamin Herrenschmidt 	return mmc_test(ast, datagen, 0xc5);
463b368e53aSBenjamin Herrenschmidt }
464b368e53aSBenjamin Herrenschmidt 
mmc_test_single2(struct ast_device * ast,u32 datagen)46537b42cf9SThomas Zimmermann static u32 mmc_test_single2(struct ast_device *ast, u32 datagen)
466b368e53aSBenjamin Herrenschmidt {
467b368e53aSBenjamin Herrenschmidt 	return mmc_test2(ast, datagen, 0x05);
468b368e53aSBenjamin Herrenschmidt }
469b368e53aSBenjamin Herrenschmidt 
mmc_test_single_2500(struct ast_device * ast,u32 datagen)47037b42cf9SThomas Zimmermann static bool mmc_test_single_2500(struct ast_device *ast, u32 datagen)
47194fdc2a8SY.C. Chen {
47294fdc2a8SY.C. Chen 	return mmc_test(ast, datagen, 0x85);
47394fdc2a8SY.C. Chen }
47494fdc2a8SY.C. Chen 
cbr_test(struct ast_device * ast)47537b42cf9SThomas Zimmermann static int cbr_test(struct ast_device *ast)
476312fec14SDave Airlie {
477312fec14SDave Airlie 	u32 data;
478312fec14SDave Airlie 	int i;
479312fec14SDave Airlie 	data = mmc_test_single2(ast, 0);
480312fec14SDave Airlie 	if ((data & 0xff) && (data & 0xff00))
481312fec14SDave Airlie 		return 0;
482312fec14SDave Airlie 	for (i = 0; i < 8; i++) {
483312fec14SDave Airlie 		data = mmc_test_burst2(ast, i);
484312fec14SDave Airlie 		if ((data & 0xff) && (data & 0xff00))
485312fec14SDave Airlie 			return 0;
486312fec14SDave Airlie 	}
487312fec14SDave Airlie 	if (!data)
488312fec14SDave Airlie 		return 3;
489312fec14SDave Airlie 	else if (data & 0xff)
490312fec14SDave Airlie 		return 2;
491312fec14SDave Airlie 	return 1;
492312fec14SDave Airlie }
493312fec14SDave Airlie 
cbr_scan(struct ast_device * ast)49437b42cf9SThomas Zimmermann static int cbr_scan(struct ast_device *ast)
495312fec14SDave Airlie {
496312fec14SDave Airlie 	u32 data, data2, patcnt, loop;
497312fec14SDave Airlie 
498312fec14SDave Airlie 	data2 = 3;
499312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
5000e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
501312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
502312fec14SDave Airlie 			if ((data = cbr_test(ast)) != 0) {
503312fec14SDave Airlie 				data2 &= data;
504312fec14SDave Airlie 				if (!data2)
505312fec14SDave Airlie 					return 0;
506312fec14SDave Airlie 				break;
507312fec14SDave Airlie 			}
508312fec14SDave Airlie 		}
509312fec14SDave Airlie 		if (loop == CBR_PASSNUM2)
510312fec14SDave Airlie 			return 0;
511312fec14SDave Airlie 	}
512312fec14SDave Airlie 	return data2;
513312fec14SDave Airlie }
514312fec14SDave Airlie 
cbr_test2(struct ast_device * ast)51537b42cf9SThomas Zimmermann static u32 cbr_test2(struct ast_device *ast)
516312fec14SDave Airlie {
517312fec14SDave Airlie 	u32 data;
518312fec14SDave Airlie 
519312fec14SDave Airlie 	data = mmc_test_burst2(ast, 0);
520312fec14SDave Airlie 	if (data == 0xffff)
521312fec14SDave Airlie 		return 0;
522312fec14SDave Airlie 	data |= mmc_test_single2(ast, 0);
523312fec14SDave Airlie 	if (data == 0xffff)
524312fec14SDave Airlie 		return 0;
525312fec14SDave Airlie 
526312fec14SDave Airlie 	return ~data & 0xffff;
527312fec14SDave Airlie }
528312fec14SDave Airlie 
cbr_scan2(struct ast_device * ast)52937b42cf9SThomas Zimmermann static u32 cbr_scan2(struct ast_device *ast)
530312fec14SDave Airlie {
531312fec14SDave Airlie 	u32 data, data2, patcnt, loop;
532312fec14SDave Airlie 
533312fec14SDave Airlie 	data2 = 0xffff;
534312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
5350e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
536312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
537312fec14SDave Airlie 			if ((data = cbr_test2(ast)) != 0) {
538312fec14SDave Airlie 				data2 &= data;
539a82049b1SDave Airlie 				if (!data2)
540312fec14SDave Airlie 					return 0;
541312fec14SDave Airlie 				break;
542312fec14SDave Airlie 			}
543312fec14SDave Airlie 		}
544312fec14SDave Airlie 		if (loop == CBR_PASSNUM2)
545312fec14SDave Airlie 			return 0;
546312fec14SDave Airlie 	}
547312fec14SDave Airlie 	return data2;
548312fec14SDave Airlie }
549312fec14SDave Airlie 
cbr_test3(struct ast_device * ast)55037b42cf9SThomas Zimmermann static bool cbr_test3(struct ast_device *ast)
551312fec14SDave Airlie {
552318cfa29SDave Airlie 	if (!mmc_test_burst(ast, 0))
553b368e53aSBenjamin Herrenschmidt 		return false;
554318cfa29SDave Airlie 	if (!mmc_test_single(ast, 0))
555b368e53aSBenjamin Herrenschmidt 		return false;
556b368e53aSBenjamin Herrenschmidt 	return true;
557318cfa29SDave Airlie }
558312fec14SDave Airlie 
cbr_scan3(struct ast_device * ast)55937b42cf9SThomas Zimmermann static bool cbr_scan3(struct ast_device *ast)
560318cfa29SDave Airlie {
561318cfa29SDave Airlie 	u32 patcnt, loop;
562312fec14SDave Airlie 
563318cfa29SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
5640e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
565318cfa29SDave Airlie 		for (loop = 0; loop < 2; loop++) {
566318cfa29SDave Airlie 			if (cbr_test3(ast))
567312fec14SDave Airlie 				break;
568312fec14SDave Airlie 		}
569318cfa29SDave Airlie 		if (loop == 2)
570b368e53aSBenjamin Herrenschmidt 			return false;
571312fec14SDave Airlie 	}
572b368e53aSBenjamin Herrenschmidt 	return true;
573312fec14SDave Airlie }
574312fec14SDave Airlie 
finetuneDQI_L(struct ast_device * ast,struct ast2300_dram_param * param)57537b42cf9SThomas Zimmermann static bool finetuneDQI_L(struct ast_device *ast, struct ast2300_dram_param *param)
576312fec14SDave Airlie {
577318cfa29SDave Airlie 	u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
578318cfa29SDave Airlie 	bool status = false;
579312fec14SDave Airlie FINETUNE_START:
580312fec14SDave Airlie 	for (cnt = 0; cnt < 16; cnt++) {
581312fec14SDave Airlie 		dllmin[cnt] = 0xff;
582312fec14SDave Airlie 		dllmax[cnt] = 0x0;
583312fec14SDave Airlie 	}
584312fec14SDave Airlie 	passcnt = 0;
585312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
5860e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24));
5870e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
588312fec14SDave Airlie 		data = cbr_scan2(ast);
589312fec14SDave Airlie 		if (data != 0) {
590312fec14SDave Airlie 			mask = 0x00010001;
591312fec14SDave Airlie 			for (cnt = 0; cnt < 16; cnt++) {
592312fec14SDave Airlie 				if (data & mask) {
593312fec14SDave Airlie 					if (dllmin[cnt] > dlli) {
594312fec14SDave Airlie 						dllmin[cnt] = dlli;
595312fec14SDave Airlie 					}
596312fec14SDave Airlie 					if (dllmax[cnt] < dlli) {
597312fec14SDave Airlie 						dllmax[cnt] = dlli;
598312fec14SDave Airlie 					}
599312fec14SDave Airlie 				}
600312fec14SDave Airlie 				mask <<= 1;
601312fec14SDave Airlie 			}
602312fec14SDave Airlie 			passcnt++;
603312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD2) {
604312fec14SDave Airlie 			break;
605312fec14SDave Airlie 		}
606312fec14SDave Airlie 	}
607312fec14SDave Airlie 	gold_sadj[0] = 0x0;
608312fec14SDave Airlie 	passcnt = 0;
609312fec14SDave Airlie 	for (cnt = 0; cnt < 16; cnt++) {
610312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
611312fec14SDave Airlie 			gold_sadj[0] += dllmin[cnt];
612312fec14SDave Airlie 			passcnt++;
613312fec14SDave Airlie 		}
614312fec14SDave Airlie 	}
615318cfa29SDave Airlie 	if (retry++ > 10)
616318cfa29SDave Airlie 		goto FINETUNE_DONE;
617312fec14SDave Airlie 	if (passcnt != 16) {
618312fec14SDave Airlie 		goto FINETUNE_START;
619312fec14SDave Airlie 	}
620318cfa29SDave Airlie 	status = true;
621318cfa29SDave Airlie FINETUNE_DONE:
622312fec14SDave Airlie 	gold_sadj[0] = gold_sadj[0] >> 4;
623312fec14SDave Airlie 	gold_sadj[1] = gold_sadj[0];
624312fec14SDave Airlie 
625312fec14SDave Airlie 	data = 0;
626312fec14SDave Airlie 	for (cnt = 0; cnt < 8; cnt++) {
627312fec14SDave Airlie 		data >>= 3;
628312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
629312fec14SDave Airlie 			dlli = dllmin[cnt];
630312fec14SDave Airlie 			if (gold_sadj[0] >= dlli) {
631312fec14SDave Airlie 				dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
632312fec14SDave Airlie 				if (dlli > 3) {
633312fec14SDave Airlie 					dlli = 3;
634312fec14SDave Airlie 				}
635312fec14SDave Airlie 			} else {
636312fec14SDave Airlie 				dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
637312fec14SDave Airlie 				if (dlli > 4) {
638312fec14SDave Airlie 					dlli = 4;
639312fec14SDave Airlie 				}
640312fec14SDave Airlie 				dlli = (8 - dlli) & 0x7;
641312fec14SDave Airlie 			}
642312fec14SDave Airlie 			data |= dlli << 21;
643312fec14SDave Airlie 		}
644312fec14SDave Airlie 	}
6450e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, data);
646312fec14SDave Airlie 
647312fec14SDave Airlie 	data = 0;
648312fec14SDave Airlie 	for (cnt = 8; cnt < 16; cnt++) {
649312fec14SDave Airlie 		data >>= 3;
650312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
651312fec14SDave Airlie 			dlli = dllmin[cnt];
652312fec14SDave Airlie 			if (gold_sadj[1] >= dlli) {
653312fec14SDave Airlie 				dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
654312fec14SDave Airlie 				if (dlli > 3) {
655312fec14SDave Airlie 					dlli = 3;
656312fec14SDave Airlie 				} else {
657312fec14SDave Airlie 					dlli = (dlli - 1) & 0x7;
658312fec14SDave Airlie 				}
659312fec14SDave Airlie 			} else {
660312fec14SDave Airlie 				dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
661312fec14SDave Airlie 				dlli += 1;
662312fec14SDave Airlie 				if (dlli > 4) {
663312fec14SDave Airlie 					dlli = 4;
664312fec14SDave Airlie 				}
665312fec14SDave Airlie 				dlli = (8 - dlli) & 0x7;
666312fec14SDave Airlie 			}
667312fec14SDave Airlie 			data |= dlli << 21;
668312fec14SDave Airlie 		}
669312fec14SDave Airlie 	}
6700e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, data);
671318cfa29SDave Airlie 	return status;
672312fec14SDave Airlie } /* finetuneDQI_L */
673312fec14SDave Airlie 
finetuneDQSI(struct ast_device * ast)67437b42cf9SThomas Zimmermann static void finetuneDQSI(struct ast_device *ast)
675312fec14SDave Airlie {
676318cfa29SDave Airlie 	u32 dlli, dqsip, dqidly;
677318cfa29SDave Airlie 	u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
678318cfa29SDave Airlie 	u32 g_dqidly, g_dqsip, g_margin, g_side;
679318cfa29SDave Airlie 	u16 pass[32][2][2];
680318cfa29SDave Airlie 	char tag[2][76];
681312fec14SDave Airlie 
682318cfa29SDave Airlie 	/* Disable DQI CBR */
6830e5ce924SDave Airlie 	reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
6840e5ce924SDave Airlie 	reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
685318cfa29SDave Airlie 	reg_mcr18 &= 0x0000ffff;
6860e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
687318cfa29SDave Airlie 
688312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
689318cfa29SDave Airlie 		tag[0][dlli] = 0x0;
690318cfa29SDave Airlie 		tag[1][dlli] = 0x0;
691312fec14SDave Airlie 	}
692318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
693318cfa29SDave Airlie 		pass[dqidly][0][0] = 0xff;
694318cfa29SDave Airlie 		pass[dqidly][0][1] = 0x0;
695318cfa29SDave Airlie 		pass[dqidly][1][0] = 0xff;
696318cfa29SDave Airlie 		pass[dqidly][1][1] = 0x0;
697312fec14SDave Airlie 	}
698318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
699318cfa29SDave Airlie 		passcnt[0] = passcnt[1] = 0;
700318cfa29SDave Airlie 		for (dqsip = 0; dqsip < 2; dqsip++) {
7010e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E000C, 0);
7020e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23));
7030e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
704318cfa29SDave Airlie 			for (dlli = 0; dlli < 76; dlli++) {
7050e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
7060e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0070, 0);
7070e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
708318cfa29SDave Airlie 				if (cbr_scan3(ast)) {
709318cfa29SDave Airlie 					if (dlli == 0)
710312fec14SDave Airlie 						break;
711318cfa29SDave Airlie 					passcnt[dqsip]++;
712318cfa29SDave Airlie 					tag[dqsip][dlli] = 'P';
713318cfa29SDave Airlie 					if (dlli < pass[dqidly][dqsip][0])
714318cfa29SDave Airlie 						pass[dqidly][dqsip][0] = (u16) dlli;
715318cfa29SDave Airlie 					if (dlli > pass[dqidly][dqsip][1])
716318cfa29SDave Airlie 						pass[dqidly][dqsip][1] = (u16) dlli;
717318cfa29SDave Airlie 				} else if (passcnt[dqsip] >= 5)
718318cfa29SDave Airlie 					break;
719318cfa29SDave Airlie 				else {
720318cfa29SDave Airlie 					pass[dqidly][dqsip][0] = 0xff;
721318cfa29SDave Airlie 					pass[dqidly][dqsip][1] = 0x0;
722312fec14SDave Airlie 				}
723312fec14SDave Airlie 			}
724312fec14SDave Airlie 		}
725318cfa29SDave Airlie 		if (passcnt[0] == 0 && passcnt[1] == 0)
726318cfa29SDave Airlie 			dqidly++;
727318cfa29SDave Airlie 	}
728318cfa29SDave Airlie 	/* Search margin */
729318cfa29SDave Airlie 	g_dqidly = g_dqsip = g_margin = g_side = 0;
730312fec14SDave Airlie 
731318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
732318cfa29SDave Airlie 		for (dqsip = 0; dqsip < 2; dqsip++) {
733318cfa29SDave Airlie 			if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
734318cfa29SDave Airlie 				continue;
735318cfa29SDave Airlie 			diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
736318cfa29SDave Airlie 			if ((diff+2) < g_margin)
737318cfa29SDave Airlie 				continue;
738318cfa29SDave Airlie 			passcnt[0] = passcnt[1] = 0;
739318cfa29SDave Airlie 			for (dlli = pass[dqidly][dqsip][0]; dlli > 0  && tag[dqsip][dlli] != 0; dlli--, passcnt[0]++);
740318cfa29SDave Airlie 			for (dlli = pass[dqidly][dqsip][1]; dlli < 76 && tag[dqsip][dlli] != 0; dlli++, passcnt[1]++);
741318cfa29SDave Airlie 			if (passcnt[0] > passcnt[1])
742318cfa29SDave Airlie 				passcnt[0] = passcnt[1];
743318cfa29SDave Airlie 			passcnt[1] = 0;
744318cfa29SDave Airlie 			if (passcnt[0] > g_side)
745318cfa29SDave Airlie 				passcnt[1] = passcnt[0] - g_side;
746318cfa29SDave Airlie 			if (diff > (g_margin+1) && (passcnt[1] > 0 || passcnt[0] > 8)) {
747318cfa29SDave Airlie 				g_margin = diff;
748318cfa29SDave Airlie 				g_dqidly = dqidly;
749318cfa29SDave Airlie 				g_dqsip  = dqsip;
750318cfa29SDave Airlie 				g_side   = passcnt[0];
751318cfa29SDave Airlie 			} else if (passcnt[1] > 1 && g_side < 8) {
752318cfa29SDave Airlie 				if (diff > g_margin)
753318cfa29SDave Airlie 					g_margin = diff;
754318cfa29SDave Airlie 				g_dqidly = dqidly;
755318cfa29SDave Airlie 				g_dqsip  = dqsip;
756318cfa29SDave Airlie 				g_side   = passcnt[0];
757312fec14SDave Airlie 			}
758312fec14SDave Airlie 		}
759312fec14SDave Airlie 	}
760318cfa29SDave Airlie 	reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
7610e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
762312fec14SDave Airlie 
763312fec14SDave Airlie }
cbr_dll2(struct ast_device * ast,struct ast2300_dram_param * param)76437b42cf9SThomas Zimmermann static bool cbr_dll2(struct ast_device *ast, struct ast2300_dram_param *param)
765312fec14SDave Airlie {
766318cfa29SDave Airlie 	u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
767318cfa29SDave Airlie 	bool status = false;
768312fec14SDave Airlie 
769318cfa29SDave Airlie 	finetuneDQSI(ast);
770318cfa29SDave Airlie 	if (finetuneDQI_L(ast, param) == false)
771318cfa29SDave Airlie 		return status;
772312fec14SDave Airlie 
773312fec14SDave Airlie CBR_START2:
774312fec14SDave Airlie 	dllmin[0] = dllmin[1] = 0xff;
775312fec14SDave Airlie 	dllmax[0] = dllmax[1] = 0x0;
776312fec14SDave Airlie 	passcnt = 0;
777312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
7780e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
7790e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
780312fec14SDave Airlie 		data = cbr_scan(ast);
781312fec14SDave Airlie 		if (data != 0) {
782312fec14SDave Airlie 			if (data & 0x1) {
783312fec14SDave Airlie 				if (dllmin[0] > dlli) {
784312fec14SDave Airlie 					dllmin[0] = dlli;
785312fec14SDave Airlie 				}
786312fec14SDave Airlie 				if (dllmax[0] < dlli) {
787312fec14SDave Airlie 					dllmax[0] = dlli;
788312fec14SDave Airlie 				}
789312fec14SDave Airlie 			}
790312fec14SDave Airlie 			if (data & 0x2) {
791312fec14SDave Airlie 				if (dllmin[1] > dlli) {
792312fec14SDave Airlie 					dllmin[1] = dlli;
793312fec14SDave Airlie 				}
794312fec14SDave Airlie 				if (dllmax[1] < dlli) {
795312fec14SDave Airlie 					dllmax[1] = dlli;
796312fec14SDave Airlie 				}
797312fec14SDave Airlie 			}
798312fec14SDave Airlie 			passcnt++;
799312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD) {
800312fec14SDave Airlie 			break;
801312fec14SDave Airlie 		}
802312fec14SDave Airlie 	}
803318cfa29SDave Airlie 	if (retry++ > 10)
804318cfa29SDave Airlie 		goto CBR_DONE2;
805312fec14SDave Airlie 	if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) {
806312fec14SDave Airlie 		goto CBR_START2;
807312fec14SDave Airlie 	}
808312fec14SDave Airlie 	if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) {
809312fec14SDave Airlie 		goto CBR_START2;
810312fec14SDave Airlie 	}
811318cfa29SDave Airlie 	status = true;
812318cfa29SDave Airlie CBR_DONE2:
813312fec14SDave Airlie 	dlli  = (dllmin[1] + dllmax[1]) >> 1;
814312fec14SDave Airlie 	dlli <<= 8;
815312fec14SDave Airlie 	dlli += (dllmin[0] + dllmax[0]) >> 1;
8160e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16));
817318cfa29SDave Airlie 	return status;
818312fec14SDave Airlie } /* CBRDLL2 */
819312fec14SDave Airlie 
get_ddr3_info(struct ast_device * ast,struct ast2300_dram_param * param)82037b42cf9SThomas Zimmermann static void get_ddr3_info(struct ast_device *ast, struct ast2300_dram_param *param)
821312fec14SDave Airlie {
822312fec14SDave Airlie 	u32 trap, trap_AC2, trap_MRS;
823312fec14SDave Airlie 
8240e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
825312fec14SDave Airlie 
826312fec14SDave Airlie 	/* Ger trap info */
8270e5ce924SDave Airlie 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
828312fec14SDave Airlie 	trap_AC2  = 0x00020000 + (trap << 16);
829312fec14SDave Airlie 	trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
830312fec14SDave Airlie 	trap_MRS  = 0x00000010 + (trap << 4);
831312fec14SDave Airlie 	trap_MRS |= ((trap & 0x2) << 18);
832312fec14SDave Airlie 
833312fec14SDave Airlie 	param->reg_MADJ       = 0x00034C4C;
834312fec14SDave Airlie 	param->reg_SADJ       = 0x00001800;
835312fec14SDave Airlie 	param->reg_DRV        = 0x000000F0;
836312fec14SDave Airlie 	param->reg_PERIOD     = param->dram_freq;
837312fec14SDave Airlie 	param->rodt           = 0;
838312fec14SDave Airlie 
839312fec14SDave Airlie 	switch (param->dram_freq) {
840312fec14SDave Airlie 	case 336:
8410e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
842312fec14SDave Airlie 		param->wodt          = 0;
843312fec14SDave Airlie 		param->reg_AC1       = 0x22202725;
844312fec14SDave Airlie 		param->reg_AC2       = 0xAA007613 | trap_AC2;
845312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000BA;
846312fec14SDave Airlie 		param->reg_MRS       = 0x04001400 | trap_MRS;
847312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
848318cfa29SDave Airlie 		param->reg_IOZ       = 0x00000023;
849312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000074;
850312fec14SDave Airlie 		param->reg_FREQ      = 0x00004DC0;
851312fec14SDave Airlie 		param->madj_max      = 96;
852312fec14SDave Airlie 		param->dll2_finetune_step = 3;
853318cfa29SDave Airlie 		switch (param->dram_chipid) {
854318cfa29SDave Airlie 		default:
855318cfa29SDave Airlie 		case AST_DRAM_512Mx16:
856318cfa29SDave Airlie 		case AST_DRAM_1Gx16:
857318cfa29SDave Airlie 			param->reg_AC2   = 0xAA007613 | trap_AC2;
858318cfa29SDave Airlie 			break;
859318cfa29SDave Airlie 		case AST_DRAM_2Gx16:
860318cfa29SDave Airlie 			param->reg_AC2   = 0xAA00761C | trap_AC2;
861318cfa29SDave Airlie 			break;
862318cfa29SDave Airlie 		case AST_DRAM_4Gx16:
863318cfa29SDave Airlie 			param->reg_AC2   = 0xAA007636 | trap_AC2;
864318cfa29SDave Airlie 			break;
865318cfa29SDave Airlie 		}
866312fec14SDave Airlie 		break;
867312fec14SDave Airlie 	default:
868312fec14SDave Airlie 	case 396:
8690e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
870312fec14SDave Airlie 		param->wodt          = 1;
871312fec14SDave Airlie 		param->reg_AC1       = 0x33302825;
872312fec14SDave Airlie 		param->reg_AC2       = 0xCC009617 | trap_AC2;
873312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
874312fec14SDave Airlie 		param->reg_MRS       = 0x04001600 | trap_MRS;
875312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
876312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
877312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
878312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
879318cfa29SDave Airlie 		param->reg_FREQ      = 0x00005040;
880312fec14SDave Airlie 		param->madj_max      = 96;
881312fec14SDave Airlie 		param->dll2_finetune_step = 4;
882312fec14SDave Airlie 
883312fec14SDave Airlie 		switch (param->dram_chipid) {
884312fec14SDave Airlie 		default:
885312fec14SDave Airlie 		case AST_DRAM_512Mx16:
886312fec14SDave Airlie 		case AST_DRAM_1Gx16:
887312fec14SDave Airlie 			param->reg_AC2   = 0xCC009617 | trap_AC2;
888312fec14SDave Airlie 			break;
889312fec14SDave Airlie 		case AST_DRAM_2Gx16:
890312fec14SDave Airlie 			param->reg_AC2   = 0xCC009622 | trap_AC2;
891312fec14SDave Airlie 			break;
892312fec14SDave Airlie 		case AST_DRAM_4Gx16:
893312fec14SDave Airlie 			param->reg_AC2   = 0xCC00963F | trap_AC2;
894312fec14SDave Airlie 			break;
895312fec14SDave Airlie 		}
896312fec14SDave Airlie 		break;
897312fec14SDave Airlie 
898312fec14SDave Airlie 	case 408:
8990e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
900312fec14SDave Airlie 		param->wodt          = 1;
901312fec14SDave Airlie 		param->reg_AC1       = 0x33302825;
902312fec14SDave Airlie 		param->reg_AC2       = 0xCC009617 | trap_AC2;
903312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
904312fec14SDave Airlie 		param->reg_MRS       = 0x04001600 | trap_MRS;
905312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
906318cfa29SDave Airlie 		param->reg_IOZ       = 0x00000023;
907312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
908312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
909312fec14SDave Airlie 		param->reg_FREQ      = 0x000050C0;
910312fec14SDave Airlie 		param->madj_max      = 96;
911312fec14SDave Airlie 		param->dll2_finetune_step = 4;
912312fec14SDave Airlie 
913312fec14SDave Airlie 		switch (param->dram_chipid) {
914312fec14SDave Airlie 		default:
915312fec14SDave Airlie 		case AST_DRAM_512Mx16:
916312fec14SDave Airlie 		case AST_DRAM_1Gx16:
917312fec14SDave Airlie 			param->reg_AC2   = 0xCC009617 | trap_AC2;
918312fec14SDave Airlie 			break;
919312fec14SDave Airlie 		case AST_DRAM_2Gx16:
920312fec14SDave Airlie 			param->reg_AC2   = 0xCC009622 | trap_AC2;
921312fec14SDave Airlie 			break;
922312fec14SDave Airlie 		case AST_DRAM_4Gx16:
923312fec14SDave Airlie 			param->reg_AC2   = 0xCC00963F | trap_AC2;
924312fec14SDave Airlie 			break;
925312fec14SDave Airlie 		}
926312fec14SDave Airlie 
927312fec14SDave Airlie 		break;
928312fec14SDave Airlie 	case 456:
9290e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
930312fec14SDave Airlie 		param->wodt          = 0;
931312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
932312fec14SDave Airlie 		param->reg_AC2       = 0xCD44961A;
933312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000FC;
934312fec14SDave Airlie 		param->reg_MRS       = 0x00081830;
935312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
936312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
937312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000097;
938312fec14SDave Airlie 		param->reg_FREQ      = 0x000052C0;
939312fec14SDave Airlie 		param->madj_max      = 88;
940312fec14SDave Airlie 		param->dll2_finetune_step = 4;
941312fec14SDave Airlie 		break;
942312fec14SDave Airlie 	case 504:
9430e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0270);
944312fec14SDave Airlie 		param->wodt          = 1;
945312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
946312fec14SDave Airlie 		param->reg_AC2       = 0xDE44A61D;
947312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000117;
948312fec14SDave Airlie 		param->reg_MRS       = 0x00081A30;
949312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
950312fec14SDave Airlie 		param->reg_IOZ       = 0x070000BB;
951312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A0;
952312fec14SDave Airlie 		param->reg_FREQ      = 0x000054C0;
953312fec14SDave Airlie 		param->madj_max      = 79;
954312fec14SDave Airlie 		param->dll2_finetune_step = 4;
955312fec14SDave Airlie 		break;
956312fec14SDave Airlie 	case 528:
9570e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0290);
958312fec14SDave Airlie 		param->wodt          = 1;
959312fec14SDave Airlie 		param->rodt          = 1;
960312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
961312fec14SDave Airlie 		param->reg_AC2       = 0xEF44B61E;
962312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000125;
963312fec14SDave Airlie 		param->reg_MRS       = 0x00081A30;
964312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
965312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
966312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
967312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000088;
968312fec14SDave Airlie 		param->reg_FREQ      = 0x000055C0;
969312fec14SDave Airlie 		param->madj_max      = 76;
970312fec14SDave Airlie 		param->dll2_finetune_step = 3;
971312fec14SDave Airlie 		break;
972312fec14SDave Airlie 	case 576:
9730e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
974312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
975312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
976312fec14SDave Airlie 		param->wodt          = 1;
977312fec14SDave Airlie 		param->rodt          = 1;
978312fec14SDave Airlie 		param->reg_AC1       = 0x33302A37;
979312fec14SDave Airlie 		param->reg_AC2       = 0xEF56B61E;
980312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000013F;
981312fec14SDave Airlie 		param->reg_MRS       = 0x00101A50;
982312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
983312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
984312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
985312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
986312fec14SDave Airlie 		param->reg_FREQ      = 0x000057C0;
987312fec14SDave Airlie 		param->madj_max      = 136;
988312fec14SDave Airlie 		param->dll2_finetune_step = 3;
989312fec14SDave Airlie 		break;
990312fec14SDave Airlie 	case 600:
9910e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
992312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
993312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
994312fec14SDave Airlie 		param->wodt          = 1;
995312fec14SDave Airlie 		param->rodt          = 1;
996312fec14SDave Airlie 		param->reg_AC1       = 0x32302A37;
997312fec14SDave Airlie 		param->reg_AC2       = 0xDF56B61F;
998312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000014D;
999312fec14SDave Airlie 		param->reg_MRS       = 0x00101A50;
1000312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1001312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1002312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
1003312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1004312fec14SDave Airlie 		param->reg_FREQ      = 0x000058C0;
1005312fec14SDave Airlie 		param->madj_max      = 132;
1006312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1007312fec14SDave Airlie 		break;
1008312fec14SDave Airlie 	case 624:
10090e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0160);
1010312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
1011312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
1012312fec14SDave Airlie 		param->wodt          = 1;
1013312fec14SDave Airlie 		param->rodt          = 1;
1014312fec14SDave Airlie 		param->reg_AC1       = 0x32302A37;
1015312fec14SDave Airlie 		param->reg_AC2       = 0xEF56B621;
1016312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000015A;
1017312fec14SDave Airlie 		param->reg_MRS       = 0x02101A50;
1018312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1019312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1020312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1021312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1022312fec14SDave Airlie 		param->reg_FREQ      = 0x000059C0;
1023312fec14SDave Airlie 		param->madj_max      = 128;
1024312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1025312fec14SDave Airlie 		break;
1026312fec14SDave Airlie 	} /* switch freq */
1027312fec14SDave Airlie 
1028312fec14SDave Airlie 	switch (param->dram_chipid) {
1029312fec14SDave Airlie 	case AST_DRAM_512Mx16:
1030312fec14SDave Airlie 		param->dram_config = 0x130;
1031312fec14SDave Airlie 		break;
1032312fec14SDave Airlie 	default:
1033312fec14SDave Airlie 	case AST_DRAM_1Gx16:
1034312fec14SDave Airlie 		param->dram_config = 0x131;
1035312fec14SDave Airlie 		break;
1036312fec14SDave Airlie 	case AST_DRAM_2Gx16:
1037312fec14SDave Airlie 		param->dram_config = 0x132;
1038312fec14SDave Airlie 		break;
1039312fec14SDave Airlie 	case AST_DRAM_4Gx16:
1040312fec14SDave Airlie 		param->dram_config = 0x133;
1041312fec14SDave Airlie 		break;
104210d9b4edSDamien Lespiau 	} /* switch size */
1043312fec14SDave Airlie 
1044312fec14SDave Airlie 	switch (param->vram_size) {
1045312fec14SDave Airlie 	default:
1046312fec14SDave Airlie 	case AST_VIDMEM_SIZE_8M:
1047312fec14SDave Airlie 		param->dram_config |= 0x00;
1048312fec14SDave Airlie 		break;
1049312fec14SDave Airlie 	case AST_VIDMEM_SIZE_16M:
1050312fec14SDave Airlie 		param->dram_config |= 0x04;
1051312fec14SDave Airlie 		break;
1052312fec14SDave Airlie 	case AST_VIDMEM_SIZE_32M:
1053312fec14SDave Airlie 		param->dram_config |= 0x08;
1054312fec14SDave Airlie 		break;
1055312fec14SDave Airlie 	case AST_VIDMEM_SIZE_64M:
1056312fec14SDave Airlie 		param->dram_config |= 0x0c;
1057312fec14SDave Airlie 		break;
1058312fec14SDave Airlie 	}
1059312fec14SDave Airlie 
1060312fec14SDave Airlie }
1061312fec14SDave Airlie 
ddr3_init(struct ast_device * ast,struct ast2300_dram_param * param)106237b42cf9SThomas Zimmermann static void ddr3_init(struct ast_device *ast, struct ast2300_dram_param *param)
1063312fec14SDave Airlie {
1064318cfa29SDave Airlie 	u32 data, data2, retry = 0;
1065312fec14SDave Airlie 
1066318cfa29SDave Airlie ddr3_init_start:
10670e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
10680e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
10690e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
10700e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
1071312fec14SDave Airlie 	udelay(10);
10720e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
10730e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1074312fec14SDave Airlie 	udelay(10);
10750e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1076312fec14SDave Airlie 	udelay(10);
1077312fec14SDave Airlie 
10780e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
10790e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
10800e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
10810e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
10820e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
10830e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
10840e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
10850e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
10860e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
10870e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
10880e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
10890e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
10900e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
10910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
10920e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
10930e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
10940e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
10950e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0054, 0);
10960e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
10970e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
10980e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
10990e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
11000e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
11010e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1102312fec14SDave Airlie 	/* Wait MCLK2X lock to MCLK */
1103312fec14SDave Airlie 	do {
11040e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1105312fec14SDave Airlie 	} while (!(data & 0x08000000));
11060e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E001C);
1107312fec14SDave Airlie 	data = (data >> 8) & 0xff;
1108312fec14SDave Airlie 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
11090e5ce924SDave Airlie 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1110312fec14SDave Airlie 		if ((data2 & 0xff) > param->madj_max) {
1111312fec14SDave Airlie 			break;
1112312fec14SDave Airlie 		}
11130e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, data2);
1114312fec14SDave Airlie 		if (data2 & 0x00100000) {
1115312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 3) + 3;
1116312fec14SDave Airlie 		} else {
1117312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 2) + 5;
1118312fec14SDave Airlie 		}
11190e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1120312fec14SDave Airlie 		data2 += data & 0xff;
1121312fec14SDave Airlie 		data = data | (data2 << 8);
11220e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, data);
1123312fec14SDave Airlie 		udelay(10);
11240e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1125312fec14SDave Airlie 		udelay(10);
11260e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
11270e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1128312fec14SDave Airlie 		data = data | 0x200;
11290e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1130312fec14SDave Airlie 		do {
11310e5ce924SDave Airlie 			data = ast_mindwm(ast, 0x1E6E001C);
1132312fec14SDave Airlie 		} while (!(data & 0x08000000));
1133312fec14SDave Airlie 
11340e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1135312fec14SDave Airlie 		data = (data >> 8) & 0xff;
1136312fec14SDave Airlie 	}
11370e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
11380e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
11390e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, data);
1140312fec14SDave Airlie 
11410e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
11420e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
1143312fec14SDave Airlie 	udelay(50);
1144312fec14SDave Airlie 	/* Mode Register Setting */
11450e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
11460e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
11470e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
11480e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
11490e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
11500e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
11510e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
11520e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
11530e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1154312fec14SDave Airlie 
11550e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
1156312fec14SDave Airlie 	data = 0;
1157312fec14SDave Airlie 	if (param->wodt) {
1158312fec14SDave Airlie 		data = 0x300;
1159312fec14SDave Airlie 	}
1160312fec14SDave Airlie 	if (param->rodt) {
1161312fec14SDave Airlie 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1162312fec14SDave Airlie 	}
11630e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
1164312fec14SDave Airlie 
1165312fec14SDave Airlie 	/* Calibrate the DQSI delay */
1166318cfa29SDave Airlie 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1167318cfa29SDave Airlie 		goto ddr3_init_start;
1168312fec14SDave Airlie 
11690e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1170312fec14SDave Airlie 	/* ECC Memory Initialization */
1171312fec14SDave Airlie #ifdef ECC
11720e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
11730e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1174312fec14SDave Airlie 	do {
11750e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0070);
1176312fec14SDave Airlie 	} while (!(data & 0x00001000));
11770e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
11780e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
11790e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1180312fec14SDave Airlie #endif
1181312fec14SDave Airlie 
1182312fec14SDave Airlie 
1183312fec14SDave Airlie }
1184312fec14SDave Airlie 
get_ddr2_info(struct ast_device * ast,struct ast2300_dram_param * param)118537b42cf9SThomas Zimmermann static void get_ddr2_info(struct ast_device *ast, struct ast2300_dram_param *param)
1186312fec14SDave Airlie {
1187312fec14SDave Airlie 	u32 trap, trap_AC2, trap_MRS;
1188312fec14SDave Airlie 
11890e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
1190312fec14SDave Airlie 
1191312fec14SDave Airlie 	/* Ger trap info */
11920e5ce924SDave Airlie 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
1193312fec14SDave Airlie 	trap_AC2  = (trap << 20) | (trap << 16);
1194312fec14SDave Airlie 	trap_AC2 += 0x00110000;
1195312fec14SDave Airlie 	trap_MRS  = 0x00000040 | (trap << 4);
1196312fec14SDave Airlie 
1197312fec14SDave Airlie 
1198312fec14SDave Airlie 	param->reg_MADJ       = 0x00034C4C;
1199312fec14SDave Airlie 	param->reg_SADJ       = 0x00001800;
1200312fec14SDave Airlie 	param->reg_DRV        = 0x000000F0;
1201312fec14SDave Airlie 	param->reg_PERIOD     = param->dram_freq;
1202312fec14SDave Airlie 	param->rodt           = 0;
1203312fec14SDave Airlie 
1204312fec14SDave Airlie 	switch (param->dram_freq) {
1205312fec14SDave Airlie 	case 264:
12060e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0130);
1207312fec14SDave Airlie 		param->wodt          = 0;
1208312fec14SDave Airlie 		param->reg_AC1       = 0x11101513;
1209312fec14SDave Airlie 		param->reg_AC2       = 0x78117011;
1210312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000092;
1211312fec14SDave Airlie 		param->reg_MRS       = 0x00000842;
1212312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
1213312fec14SDave Airlie 		param->reg_DRV       = 0x000000F0;
1214312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1215312fec14SDave Airlie 		param->reg_DQIDLY    = 0x0000005A;
1216312fec14SDave Airlie 		param->reg_FREQ      = 0x00004AC0;
1217312fec14SDave Airlie 		param->madj_max      = 138;
1218312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1219312fec14SDave Airlie 		break;
1220312fec14SDave Airlie 	case 336:
12210e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
1222312fec14SDave Airlie 		param->wodt          = 1;
1223312fec14SDave Airlie 		param->reg_AC1       = 0x22202613;
1224312fec14SDave Airlie 		param->reg_AC2       = 0xAA009016 | trap_AC2;
1225312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000BA;
1226312fec14SDave Airlie 		param->reg_MRS       = 0x00000A02 | trap_MRS;
1227312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1228312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1229312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1230312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000074;
1231312fec14SDave Airlie 		param->reg_FREQ      = 0x00004DC0;
1232312fec14SDave Airlie 		param->madj_max      = 96;
1233312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1234318cfa29SDave Airlie 		switch (param->dram_chipid) {
1235318cfa29SDave Airlie 		default:
1236318cfa29SDave Airlie 		case AST_DRAM_512Mx16:
1237318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009012 | trap_AC2;
1238318cfa29SDave Airlie 			break;
1239318cfa29SDave Airlie 		case AST_DRAM_1Gx16:
1240318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009016 | trap_AC2;
1241318cfa29SDave Airlie 			break;
1242318cfa29SDave Airlie 		case AST_DRAM_2Gx16:
1243318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009023 | trap_AC2;
1244318cfa29SDave Airlie 			break;
1245318cfa29SDave Airlie 		case AST_DRAM_4Gx16:
1246318cfa29SDave Airlie 			param->reg_AC2   = 0xAA00903B | trap_AC2;
1247318cfa29SDave Airlie 			break;
1248318cfa29SDave Airlie 		}
1249312fec14SDave Airlie 		break;
1250312fec14SDave Airlie 	default:
1251312fec14SDave Airlie 	case 396:
12520e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
1253312fec14SDave Airlie 		param->wodt          = 1;
1254312fec14SDave Airlie 		param->rodt          = 0;
1255312fec14SDave Airlie 		param->reg_AC1       = 0x33302714;
1256312fec14SDave Airlie 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1257312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
1258312fec14SDave Airlie 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1259312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1260312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1261312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1262312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
1263318cfa29SDave Airlie 		param->reg_FREQ      = 0x00005040;
1264312fec14SDave Airlie 		param->madj_max      = 96;
1265312fec14SDave Airlie 		param->dll2_finetune_step = 4;
1266312fec14SDave Airlie 
1267312fec14SDave Airlie 		switch (param->dram_chipid) {
1268312fec14SDave Airlie 		case AST_DRAM_512Mx16:
1269312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1270312fec14SDave Airlie 			break;
1271312fec14SDave Airlie 		default:
1272312fec14SDave Airlie 		case AST_DRAM_1Gx16:
1273312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1274312fec14SDave Airlie 			break;
1275312fec14SDave Airlie 		case AST_DRAM_2Gx16:
1276312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1277312fec14SDave Airlie 			break;
1278312fec14SDave Airlie 		case AST_DRAM_4Gx16:
1279312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1280312fec14SDave Airlie 			break;
1281312fec14SDave Airlie 		}
1282312fec14SDave Airlie 
1283312fec14SDave Airlie 		break;
1284312fec14SDave Airlie 
1285312fec14SDave Airlie 	case 408:
12860e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
1287312fec14SDave Airlie 		param->wodt          = 1;
1288312fec14SDave Airlie 		param->rodt          = 0;
1289312fec14SDave Airlie 		param->reg_AC1       = 0x33302714;
1290312fec14SDave Airlie 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1291312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
1292312fec14SDave Airlie 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1293312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1294312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1295312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1296312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
1297312fec14SDave Airlie 		param->reg_FREQ      = 0x000050C0;
1298312fec14SDave Airlie 		param->madj_max      = 96;
1299312fec14SDave Airlie 		param->dll2_finetune_step = 4;
1300312fec14SDave Airlie 
1301312fec14SDave Airlie 		switch (param->dram_chipid) {
1302312fec14SDave Airlie 		case AST_DRAM_512Mx16:
1303312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1304312fec14SDave Airlie 			break;
1305312fec14SDave Airlie 		default:
1306312fec14SDave Airlie 		case AST_DRAM_1Gx16:
1307312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1308312fec14SDave Airlie 			break;
1309312fec14SDave Airlie 		case AST_DRAM_2Gx16:
1310312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1311312fec14SDave Airlie 			break;
1312312fec14SDave Airlie 		case AST_DRAM_4Gx16:
1313312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1314312fec14SDave Airlie 			break;
1315312fec14SDave Airlie 		}
1316312fec14SDave Airlie 
1317312fec14SDave Airlie 		break;
1318312fec14SDave Airlie 	case 456:
13190e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
1320312fec14SDave Airlie 		param->wodt          = 0;
1321312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1322312fec14SDave Airlie 		param->reg_AC2       = 0xCD44B01E;
1323312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000FC;
1324312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1325312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
1326312fec14SDave Airlie 		param->reg_DRV       = 0x00000000;
1327312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1328312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000097;
1329312fec14SDave Airlie 		param->reg_FREQ      = 0x000052C0;
1330312fec14SDave Airlie 		param->madj_max      = 88;
1331312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1332312fec14SDave Airlie 		break;
1333312fec14SDave Airlie 	case 504:
13340e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0261);
1335312fec14SDave Airlie 		param->wodt          = 1;
1336312fec14SDave Airlie 		param->rodt          = 1;
1337312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1338312fec14SDave Airlie 		param->reg_AC2       = 0xDE44C022;
1339312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000117;
1340312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1341312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1342312fec14SDave Airlie 		param->reg_DRV       = 0x0000000A;
1343312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1344312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A0;
1345312fec14SDave Airlie 		param->reg_FREQ      = 0x000054C0;
1346312fec14SDave Airlie 		param->madj_max      = 79;
1347312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1348312fec14SDave Airlie 		break;
1349312fec14SDave Airlie 	case 528:
13500e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0120);
1351312fec14SDave Airlie 		param->wodt          = 1;
1352312fec14SDave Airlie 		param->rodt          = 1;
1353312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1354312fec14SDave Airlie 		param->reg_AC2       = 0xEF44D024;
1355312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000125;
1356312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1357312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1358312fec14SDave Airlie 		param->reg_DRV       = 0x000000F9;
1359312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1360312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A7;
1361312fec14SDave Airlie 		param->reg_FREQ      = 0x000055C0;
1362312fec14SDave Airlie 		param->madj_max      = 76;
1363312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1364312fec14SDave Airlie 		break;
1365312fec14SDave Airlie 	case 552:
13660e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
1367312fec14SDave Airlie 		param->wodt          = 1;
1368312fec14SDave Airlie 		param->rodt          = 1;
1369312fec14SDave Airlie 		param->reg_AC1       = 0x43402915;
1370312fec14SDave Airlie 		param->reg_AC2       = 0xFF44E025;
1371312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000132;
1372312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1373312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1374312fec14SDave Airlie 		param->reg_DRV       = 0x0000000A;
1375312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1376312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000AD;
1377312fec14SDave Airlie 		param->reg_FREQ      = 0x000056C0;
1378312fec14SDave Airlie 		param->madj_max      = 76;
1379312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1380312fec14SDave Airlie 		break;
1381312fec14SDave Airlie 	case 576:
13820e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1383312fec14SDave Airlie 		param->wodt          = 1;
1384312fec14SDave Airlie 		param->rodt          = 1;
1385312fec14SDave Airlie 		param->reg_AC1       = 0x43402915;
1386312fec14SDave Airlie 		param->reg_AC2       = 0xFF44E027;
1387312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000013F;
1388312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1389312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1390312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1391312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1392312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000B3;
1393312fec14SDave Airlie 		param->reg_FREQ      = 0x000057C0;
1394312fec14SDave Airlie 		param->madj_max      = 76;
1395312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1396312fec14SDave Airlie 		break;
1397312fec14SDave Airlie 	}
1398312fec14SDave Airlie 
1399312fec14SDave Airlie 	switch (param->dram_chipid) {
1400312fec14SDave Airlie 	case AST_DRAM_512Mx16:
1401312fec14SDave Airlie 		param->dram_config = 0x100;
1402312fec14SDave Airlie 		break;
1403312fec14SDave Airlie 	default:
1404312fec14SDave Airlie 	case AST_DRAM_1Gx16:
1405312fec14SDave Airlie 		param->dram_config = 0x121;
1406312fec14SDave Airlie 		break;
1407312fec14SDave Airlie 	case AST_DRAM_2Gx16:
1408312fec14SDave Airlie 		param->dram_config = 0x122;
1409312fec14SDave Airlie 		break;
1410312fec14SDave Airlie 	case AST_DRAM_4Gx16:
1411312fec14SDave Airlie 		param->dram_config = 0x123;
1412312fec14SDave Airlie 		break;
141310d9b4edSDamien Lespiau 	} /* switch size */
1414312fec14SDave Airlie 
1415312fec14SDave Airlie 	switch (param->vram_size) {
1416312fec14SDave Airlie 	default:
1417312fec14SDave Airlie 	case AST_VIDMEM_SIZE_8M:
1418312fec14SDave Airlie 		param->dram_config |= 0x00;
1419312fec14SDave Airlie 		break;
1420312fec14SDave Airlie 	case AST_VIDMEM_SIZE_16M:
1421312fec14SDave Airlie 		param->dram_config |= 0x04;
1422312fec14SDave Airlie 		break;
1423312fec14SDave Airlie 	case AST_VIDMEM_SIZE_32M:
1424312fec14SDave Airlie 		param->dram_config |= 0x08;
1425312fec14SDave Airlie 		break;
1426312fec14SDave Airlie 	case AST_VIDMEM_SIZE_64M:
1427312fec14SDave Airlie 		param->dram_config |= 0x0c;
1428312fec14SDave Airlie 		break;
1429312fec14SDave Airlie 	}
1430312fec14SDave Airlie }
1431312fec14SDave Airlie 
ddr2_init(struct ast_device * ast,struct ast2300_dram_param * param)143237b42cf9SThomas Zimmermann static void ddr2_init(struct ast_device *ast, struct ast2300_dram_param *param)
1433312fec14SDave Airlie {
1434318cfa29SDave Airlie 	u32 data, data2, retry = 0;
1435312fec14SDave Airlie 
1436318cfa29SDave Airlie ddr2_init_start:
14370e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
14380e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
14390e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
14400e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
14410e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1442312fec14SDave Airlie 	udelay(10);
14430e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1444312fec14SDave Airlie 	udelay(10);
1445312fec14SDave Airlie 
14460e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
14470e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
14480e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
14490e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
14500e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
14510e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
14520e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
14530e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
14540e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
14550e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
14560e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
14570e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
14580e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
14590e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
14600e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
14610e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
14620e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
14630e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0054, 0);
14640e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
14650e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
14660e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
14670e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
14680e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
14690e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1470312fec14SDave Airlie 
1471312fec14SDave Airlie 	/* Wait MCLK2X lock to MCLK */
1472312fec14SDave Airlie 	do {
14730e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1474312fec14SDave Airlie 	} while (!(data & 0x08000000));
14750e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E001C);
1476312fec14SDave Airlie 	data = (data >> 8) & 0xff;
1477312fec14SDave Airlie 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
14780e5ce924SDave Airlie 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1479312fec14SDave Airlie 		if ((data2 & 0xff) > param->madj_max) {
1480312fec14SDave Airlie 			break;
1481312fec14SDave Airlie 		}
14820e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, data2);
1483312fec14SDave Airlie 		if (data2 & 0x00100000) {
1484312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 3) + 3;
1485312fec14SDave Airlie 		} else {
1486312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 2) + 5;
1487312fec14SDave Airlie 		}
14880e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1489312fec14SDave Airlie 		data2 += data & 0xff;
1490312fec14SDave Airlie 		data = data | (data2 << 8);
14910e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, data);
1492312fec14SDave Airlie 		udelay(10);
14930e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1494312fec14SDave Airlie 		udelay(10);
14950e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
14960e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1497312fec14SDave Airlie 		data = data | 0x200;
14980e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1499312fec14SDave Airlie 		do {
15000e5ce924SDave Airlie 			data = ast_mindwm(ast, 0x1E6E001C);
1501312fec14SDave Airlie 		} while (!(data & 0x08000000));
1502312fec14SDave Airlie 
15030e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1504312fec14SDave Airlie 		data = (data >> 8) & 0xff;
1505312fec14SDave Airlie 	}
15060e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
15070e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
15080e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, data);
1509312fec14SDave Airlie 
15100e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
15110e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1512312fec14SDave Airlie 	udelay(50);
1513312fec14SDave Airlie 	/* Mode Register Setting */
15140e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
15150e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
15160e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
15170e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
15180e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
15190e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1520312fec14SDave Airlie 
15210e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
15220e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
15230e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
15240e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
15250e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
15260e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
15270e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1528312fec14SDave Airlie 
15290e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
1530312fec14SDave Airlie 	data = 0;
1531312fec14SDave Airlie 	if (param->wodt) {
1532312fec14SDave Airlie 		data = 0x500;
1533312fec14SDave Airlie 	}
1534312fec14SDave Airlie 	if (param->rodt) {
1535312fec14SDave Airlie 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1536312fec14SDave Airlie 	}
15370e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
15380e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1539312fec14SDave Airlie 
1540312fec14SDave Airlie 	/* Calibrate the DQSI delay */
1541318cfa29SDave Airlie 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1542318cfa29SDave Airlie 		goto ddr2_init_start;
1543312fec14SDave Airlie 
1544312fec14SDave Airlie 	/* ECC Memory Initialization */
1545312fec14SDave Airlie #ifdef ECC
15460e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
15470e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1548312fec14SDave Airlie 	do {
15490e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0070);
1550312fec14SDave Airlie 	} while (!(data & 0x00001000));
15510e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
15520e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
15530e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1554312fec14SDave Airlie #endif
1555312fec14SDave Airlie 
1556312fec14SDave Airlie }
1557312fec14SDave Airlie 
ast_post_chip_2300(struct drm_device * dev)1558d95618efSBenjamin Herrenschmidt static void ast_post_chip_2300(struct drm_device *dev)
1559312fec14SDave Airlie {
15605abaa683SThomas Zimmermann 	struct ast_device *ast = to_ast_device(dev);
1561312fec14SDave Airlie 	struct ast2300_dram_param param;
1562312fec14SDave Airlie 	u32 temp;
1563312fec14SDave Airlie 	u8 reg;
1564312fec14SDave Airlie 
1565312fec14SDave Airlie 	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1566312fec14SDave Airlie 	if ((reg & 0x80) == 0) {/* vga only */
1567312fec14SDave Airlie 		ast_write32(ast, 0xf004, 0x1e6e0000);
1568312fec14SDave Airlie 		ast_write32(ast, 0xf000, 0x1);
1569312fec14SDave Airlie 		ast_write32(ast, 0x12000, 0x1688a8a8);
1570312fec14SDave Airlie 		do {
1571312fec14SDave Airlie 			;
1572312fec14SDave Airlie 		} while (ast_read32(ast, 0x12000) != 0x1);
1573312fec14SDave Airlie 
1574312fec14SDave Airlie 		ast_write32(ast, 0x10000, 0xfc600309);
1575312fec14SDave Airlie 		do {
1576312fec14SDave Airlie 			;
1577312fec14SDave Airlie 		} while (ast_read32(ast, 0x10000) != 0x1);
1578312fec14SDave Airlie 
1579312fec14SDave Airlie 		/* Slow down CPU/AHB CLK in VGA only mode */
1580312fec14SDave Airlie 		temp = ast_read32(ast, 0x12008);
1581312fec14SDave Airlie 		temp |= 0x73;
1582312fec14SDave Airlie 		ast_write32(ast, 0x12008, temp);
1583312fec14SDave Airlie 
15843856081eSY.C. Chen 		param.dram_freq = 396;
1585312fec14SDave Airlie 		param.dram_type = AST_DDR3;
15863856081eSY.C. Chen 		temp = ast_mindwm(ast, 0x1e6e2070);
1587312fec14SDave Airlie 		if (temp & 0x01000000)
1588312fec14SDave Airlie 			param.dram_type = AST_DDR2;
15893856081eSY.C. Chen                 switch (temp & 0x18000000) {
15903856081eSY.C. Chen 		case 0:
15913856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_512Mx16;
15923856081eSY.C. Chen 			break;
15933856081eSY.C. Chen 		default:
15943856081eSY.C. Chen 		case 0x08000000:
15953856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_1Gx16;
15963856081eSY.C. Chen 			break;
15973856081eSY.C. Chen 		case 0x10000000:
15983856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_2Gx16;
15993856081eSY.C. Chen 			break;
16003856081eSY.C. Chen 		case 0x18000000:
16013856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_4Gx16;
16023856081eSY.C. Chen 			break;
16033856081eSY.C. Chen 		}
16043856081eSY.C. Chen                 switch (temp & 0x0c) {
16053856081eSY.C. Chen                 default:
16063856081eSY.C. Chen 		case 0x00:
16073856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_8M;
16083856081eSY.C. Chen 			break;
16093856081eSY.C. Chen 
16103856081eSY.C. Chen 		case 0x04:
16113856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_16M;
16123856081eSY.C. Chen 			break;
16133856081eSY.C. Chen 
16143856081eSY.C. Chen 		case 0x08:
16153856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_32M;
16163856081eSY.C. Chen 			break;
16173856081eSY.C. Chen 
16183856081eSY.C. Chen 		case 0x0c:
16193856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_64M;
16203856081eSY.C. Chen 			break;
16213856081eSY.C. Chen 		}
1622312fec14SDave Airlie 
1623312fec14SDave Airlie 		if (param.dram_type == AST_DDR3) {
1624312fec14SDave Airlie 			get_ddr3_info(ast, &param);
1625312fec14SDave Airlie 			ddr3_init(ast, &param);
1626312fec14SDave Airlie 		} else {
1627312fec14SDave Airlie 			get_ddr2_info(ast, &param);
1628312fec14SDave Airlie 			ddr2_init(ast, &param);
1629312fec14SDave Airlie 		}
1630312fec14SDave Airlie 
16310e5ce924SDave Airlie 		temp = ast_mindwm(ast, 0x1e6e2040);
16320e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
1633312fec14SDave Airlie 	}
1634312fec14SDave Airlie 
1635312fec14SDave Airlie 	/* wait ready */
1636312fec14SDave Airlie 	do {
1637312fec14SDave Airlie 		reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1638312fec14SDave Airlie 	} while ((reg & 0x40) == 0);
1639312fec14SDave Airlie }
1640312fec14SDave Airlie 
cbr_test_2500(struct ast_device * ast)164137b42cf9SThomas Zimmermann static bool cbr_test_2500(struct ast_device *ast)
164294fdc2a8SY.C. Chen {
164394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
164494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
164594fdc2a8SY.C. Chen 	if (!mmc_test_burst(ast, 0))
164694fdc2a8SY.C. Chen 		return false;
164794fdc2a8SY.C. Chen 	if (!mmc_test_single_2500(ast, 0))
164894fdc2a8SY.C. Chen 		return false;
164994fdc2a8SY.C. Chen 	return true;
165094fdc2a8SY.C. Chen }
165194fdc2a8SY.C. Chen 
ddr_test_2500(struct ast_device * ast)165237b42cf9SThomas Zimmermann static bool ddr_test_2500(struct ast_device *ast)
165394fdc2a8SY.C. Chen {
165494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
165594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
165694fdc2a8SY.C. Chen 	if (!mmc_test_burst(ast, 0))
165794fdc2a8SY.C. Chen 		return false;
165894fdc2a8SY.C. Chen 	if (!mmc_test_burst(ast, 1))
165994fdc2a8SY.C. Chen 		return false;
166094fdc2a8SY.C. Chen 	if (!mmc_test_burst(ast, 2))
166194fdc2a8SY.C. Chen 		return false;
166294fdc2a8SY.C. Chen 	if (!mmc_test_burst(ast, 3))
166394fdc2a8SY.C. Chen 		return false;
166494fdc2a8SY.C. Chen 	if (!mmc_test_single_2500(ast, 0))
166594fdc2a8SY.C. Chen 		return false;
166694fdc2a8SY.C. Chen 	return true;
166794fdc2a8SY.C. Chen }
166894fdc2a8SY.C. Chen 
ddr_init_common_2500(struct ast_device * ast)166937b42cf9SThomas Zimmermann static void ddr_init_common_2500(struct ast_device *ast)
167094fdc2a8SY.C. Chen {
167194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
167294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0008, 0x2003000F);
167394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0038, 0x00000FFF);
167494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0040, 0x88448844);
167594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0044, 0x24422288);
167694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
167794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E004C, 0x22222222);
167894fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
167994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0208, 0x00000000);
168094fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0218, 0x00000000);
168194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0220, 0x00000000);
168294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0228, 0x00000000);
168394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0230, 0x00000000);
168494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02A8, 0x00000000);
168594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02B0, 0x00000000);
168694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0240, 0x86000000);
168794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0244, 0x00008600);
168894fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0248, 0x80000000);
168994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E024C, 0x80808080);
169094fdc2a8SY.C. Chen }
169194fdc2a8SY.C. Chen 
ddr_phy_init_2500(struct ast_device * ast)169237b42cf9SThomas Zimmermann static void ddr_phy_init_2500(struct ast_device *ast)
169394fdc2a8SY.C. Chen {
169494fdc2a8SY.C. Chen 	u32 data, pass, timecnt;
169594fdc2a8SY.C. Chen 
169694fdc2a8SY.C. Chen 	pass = 0;
169794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
169894fdc2a8SY.C. Chen 	while (!pass) {
169994fdc2a8SY.C. Chen 		for (timecnt = 0; timecnt < TIMEOUT; timecnt++) {
170094fdc2a8SY.C. Chen 			data = ast_mindwm(ast, 0x1E6E0060) & 0x1;
170194fdc2a8SY.C. Chen 			if (!data)
170294fdc2a8SY.C. Chen 				break;
170394fdc2a8SY.C. Chen 		}
170494fdc2a8SY.C. Chen 		if (timecnt != TIMEOUT) {
170594fdc2a8SY.C. Chen 			data = ast_mindwm(ast, 0x1E6E0300) & 0x000A0000;
170694fdc2a8SY.C. Chen 			if (!data)
170794fdc2a8SY.C. Chen 				pass = 1;
170894fdc2a8SY.C. Chen 		}
170994fdc2a8SY.C. Chen 		if (!pass) {
171094fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
171194fdc2a8SY.C. Chen 			udelay(10); /* delay 10 us */
171294fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
171394fdc2a8SY.C. Chen 		}
171494fdc2a8SY.C. Chen 	}
171594fdc2a8SY.C. Chen 
171694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0060, 0x00000006);
171794fdc2a8SY.C. Chen }
171894fdc2a8SY.C. Chen 
171994fdc2a8SY.C. Chen /*
172094fdc2a8SY.C. Chen  * Check DRAM Size
172194fdc2a8SY.C. Chen  * 1Gb : 0x80000000 ~ 0x87FFFFFF
172294fdc2a8SY.C. Chen  * 2Gb : 0x80000000 ~ 0x8FFFFFFF
172394fdc2a8SY.C. Chen  * 4Gb : 0x80000000 ~ 0x9FFFFFFF
172494fdc2a8SY.C. Chen  * 8Gb : 0x80000000 ~ 0xBFFFFFFF
172594fdc2a8SY.C. Chen  */
check_dram_size_2500(struct ast_device * ast,u32 tRFC)172637b42cf9SThomas Zimmermann static void check_dram_size_2500(struct ast_device *ast, u32 tRFC)
172794fdc2a8SY.C. Chen {
172894fdc2a8SY.C. Chen 	u32 reg_04, reg_14;
172994fdc2a8SY.C. Chen 
173094fdc2a8SY.C. Chen 	reg_04 = ast_mindwm(ast, 0x1E6E0004) & 0xfffffffc;
173194fdc2a8SY.C. Chen 	reg_14 = ast_mindwm(ast, 0x1E6E0014) & 0xffffff00;
173294fdc2a8SY.C. Chen 
173394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0xA0100000, 0x41424344);
173494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x90100000, 0x35363738);
173594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x88100000, 0x292A2B2C);
173694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x80100000, 0x1D1E1F10);
173794fdc2a8SY.C. Chen 
173894fdc2a8SY.C. Chen 	/* Check 8Gbit */
173994fdc2a8SY.C. Chen 	if (ast_mindwm(ast, 0xA0100000) == 0x41424344) {
174094fdc2a8SY.C. Chen 		reg_04 |= 0x03;
174194fdc2a8SY.C. Chen 		reg_14 |= (tRFC >> 24) & 0xFF;
174294fdc2a8SY.C. Chen 		/* Check 4Gbit */
174394fdc2a8SY.C. Chen 	} else if (ast_mindwm(ast, 0x90100000) == 0x35363738) {
174494fdc2a8SY.C. Chen 		reg_04 |= 0x02;
174594fdc2a8SY.C. Chen 		reg_14 |= (tRFC >> 16) & 0xFF;
174694fdc2a8SY.C. Chen 		/* Check 2Gbit */
174794fdc2a8SY.C. Chen 	} else if (ast_mindwm(ast, 0x88100000) == 0x292A2B2C) {
174894fdc2a8SY.C. Chen 		reg_04 |= 0x01;
174994fdc2a8SY.C. Chen 		reg_14 |= (tRFC >> 8) & 0xFF;
175094fdc2a8SY.C. Chen 	} else {
175194fdc2a8SY.C. Chen 		reg_14 |= tRFC & 0xFF;
175294fdc2a8SY.C. Chen 	}
175394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0004, reg_04);
175494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0014, reg_14);
175594fdc2a8SY.C. Chen }
175694fdc2a8SY.C. Chen 
enable_cache_2500(struct ast_device * ast)175737b42cf9SThomas Zimmermann static void enable_cache_2500(struct ast_device *ast)
175894fdc2a8SY.C. Chen {
175994fdc2a8SY.C. Chen 	u32 reg_04, data;
176094fdc2a8SY.C. Chen 
176194fdc2a8SY.C. Chen 	reg_04 = ast_mindwm(ast, 0x1E6E0004);
176294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x1000);
176394fdc2a8SY.C. Chen 
176494fdc2a8SY.C. Chen 	do
176594fdc2a8SY.C. Chen 		data = ast_mindwm(ast, 0x1E6E0004);
176694fdc2a8SY.C. Chen 	while (!(data & 0x80000));
176794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
176894fdc2a8SY.C. Chen }
176994fdc2a8SY.C. Chen 
set_mpll_2500(struct ast_device * ast)177037b42cf9SThomas Zimmermann static void set_mpll_2500(struct ast_device *ast)
177194fdc2a8SY.C. Chen {
177294fdc2a8SY.C. Chen 	u32 addr, data, param;
177394fdc2a8SY.C. Chen 
177494fdc2a8SY.C. Chen 	/* Reset MMC */
177594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
177694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
177794fdc2a8SY.C. Chen 	for (addr = 0x1e6e0004; addr < 0x1e6e0090;) {
177894fdc2a8SY.C. Chen 		ast_moutdwm(ast, addr, 0x0);
177994fdc2a8SY.C. Chen 		addr += 4;
178094fdc2a8SY.C. Chen 	}
178194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0034, 0x00020000);
178294fdc2a8SY.C. Chen 
178394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
178494fdc2a8SY.C. Chen 	data = ast_mindwm(ast, 0x1E6E2070) & 0x00800000;
178594fdc2a8SY.C. Chen 	if (data) {
178694fdc2a8SY.C. Chen 		/* CLKIN = 25MHz */
178794fdc2a8SY.C. Chen 		param = 0x930023E0;
178894fdc2a8SY.C. Chen 		ast_moutdwm(ast, 0x1E6E2160, 0x00011320);
178994fdc2a8SY.C. Chen 	} else {
179094fdc2a8SY.C. Chen 		/* CLKIN = 24MHz */
179194fdc2a8SY.C. Chen 		param = 0x93002400;
179294fdc2a8SY.C. Chen 	}
179394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E2020, param);
179494fdc2a8SY.C. Chen 	udelay(100);
179594fdc2a8SY.C. Chen }
179694fdc2a8SY.C. Chen 
reset_mmc_2500(struct ast_device * ast)179737b42cf9SThomas Zimmermann static void reset_mmc_2500(struct ast_device *ast)
179894fdc2a8SY.C. Chen {
179994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E78505C, 0x00000004);
180094fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E785044, 0x00000001);
180194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E785048, 0x00004755);
180294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E78504C, 0x00000013);
180394fdc2a8SY.C. Chen 	mdelay(100);
180494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E785054, 0x00000077);
180594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
180694fdc2a8SY.C. Chen }
180794fdc2a8SY.C. Chen 
ddr3_init_2500(struct ast_device * ast,const u32 * ddr_table)180837b42cf9SThomas Zimmermann static void ddr3_init_2500(struct ast_device *ast, const u32 *ddr_table)
180994fdc2a8SY.C. Chen {
181094fdc2a8SY.C. Chen 
181194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0004, 0x00000303);
181294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
181394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
181494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
181594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]);	     /* MODEREG4/6 */
181694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]);	     /* MODEREG5 */
181794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
181894fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]);	     /* MODEREG1/3 */
181994fdc2a8SY.C. Chen 
182094fdc2a8SY.C. Chen 	/* DDR PHY Setting */
182194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0200, 0x02492AAE);
182294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0204, 0x00001001);
182394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
182494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
182594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
182694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
182794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
182894fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
182994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
183094fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
183194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
183294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
183394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
183494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02C0, 0x00000006);
183594fdc2a8SY.C. Chen 
183694fdc2a8SY.C. Chen 	/* Controller Setting */
183794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0034, 0x00020091);
183894fdc2a8SY.C. Chen 
183994fdc2a8SY.C. Chen 	/* Wait DDR PHY init done */
184094fdc2a8SY.C. Chen 	ddr_phy_init_2500(ast);
184194fdc2a8SY.C. Chen 
184294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
184394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
184494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
184594fdc2a8SY.C. Chen 
184694fdc2a8SY.C. Chen 	check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
184794fdc2a8SY.C. Chen 	enable_cache_2500(ast);
184894fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
184994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
185094fdc2a8SY.C. Chen }
185194fdc2a8SY.C. Chen 
ddr4_init_2500(struct ast_device * ast,const u32 * ddr_table)185237b42cf9SThomas Zimmermann static void ddr4_init_2500(struct ast_device *ast, const u32 *ddr_table)
185394fdc2a8SY.C. Chen {
185494fdc2a8SY.C. Chen 	u32 data, data2, pass, retrycnt;
185594fdc2a8SY.C. Chen 	u32 ddr_vref, phy_vref;
185694fdc2a8SY.C. Chen 	u32 min_ddr_vref = 0, min_phy_vref = 0;
185794fdc2a8SY.C. Chen 	u32 max_ddr_vref = 0, max_phy_vref = 0;
185894fdc2a8SY.C. Chen 
185994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0004, 0x00000313);
186094fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
186194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
186294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
186394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]);	     /* MODEREG4/6 */
186494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]);	     /* MODEREG5 */
186594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
186694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]);	     /* MODEREG1/3 */
186794fdc2a8SY.C. Chen 
186894fdc2a8SY.C. Chen 	/* DDR PHY Setting */
186994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0200, 0x42492AAE);
187094fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0204, 0x09002000);
187194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
187294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
187394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
187494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
187594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
187694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
187794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
187894fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
187994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
188094fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
188194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
188294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02C4, 0x3C183C3C);
188394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02C8, 0x00631E0E);
188494fdc2a8SY.C. Chen 
188594fdc2a8SY.C. Chen 	/* Controller Setting */
188694fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0034, 0x0001A991);
188794fdc2a8SY.C. Chen 
188894fdc2a8SY.C. Chen 	/* Train PHY Vref first */
188994fdc2a8SY.C. Chen 	pass = 0;
189094fdc2a8SY.C. Chen 
189194fdc2a8SY.C. Chen 	for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
189294fdc2a8SY.C. Chen 		max_phy_vref = 0x0;
189394fdc2a8SY.C. Chen 		pass = 0;
189494fdc2a8SY.C. Chen 		ast_moutdwm(ast, 0x1E6E02C0, 0x00001C06);
189594fdc2a8SY.C. Chen 		for (phy_vref = 0x40; phy_vref < 0x80; phy_vref++) {
189694fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
189794fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
189894fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E02CC, phy_vref | (phy_vref << 8));
189994fdc2a8SY.C. Chen 			/* Fire DFI Init */
190094fdc2a8SY.C. Chen 			ddr_phy_init_2500(ast);
190194fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
190294fdc2a8SY.C. Chen 			if (cbr_test_2500(ast)) {
190394fdc2a8SY.C. Chen 				pass++;
190494fdc2a8SY.C. Chen 				data = ast_mindwm(ast, 0x1E6E03D0);
190594fdc2a8SY.C. Chen 				data2 = data >> 8;
190694fdc2a8SY.C. Chen 				data  = data & 0xff;
190794fdc2a8SY.C. Chen 				if (data > data2)
190894fdc2a8SY.C. Chen 					data = data2;
190994fdc2a8SY.C. Chen 				if (max_phy_vref < data) {
191094fdc2a8SY.C. Chen 					max_phy_vref = data;
191194fdc2a8SY.C. Chen 					min_phy_vref = phy_vref;
191294fdc2a8SY.C. Chen 				}
191394fdc2a8SY.C. Chen 			} else if (pass > 0)
191494fdc2a8SY.C. Chen 				break;
191594fdc2a8SY.C. Chen 		}
191694fdc2a8SY.C. Chen 	}
191794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02CC, min_phy_vref | (min_phy_vref << 8));
191894fdc2a8SY.C. Chen 
191994fdc2a8SY.C. Chen 	/* Train DDR Vref next */
192094fdc2a8SY.C. Chen 	pass = 0;
192194fdc2a8SY.C. Chen 
192294fdc2a8SY.C. Chen 	for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
192394fdc2a8SY.C. Chen 		min_ddr_vref = 0xFF;
192494fdc2a8SY.C. Chen 		max_ddr_vref = 0x0;
192594fdc2a8SY.C. Chen 		pass = 0;
192694fdc2a8SY.C. Chen 		for (ddr_vref = 0x00; ddr_vref < 0x40; ddr_vref++) {
192794fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
192894fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
192994fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
193094fdc2a8SY.C. Chen 			/* Fire DFI Init */
193194fdc2a8SY.C. Chen 			ddr_phy_init_2500(ast);
193294fdc2a8SY.C. Chen 			ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
193394fdc2a8SY.C. Chen 			if (cbr_test_2500(ast)) {
193494fdc2a8SY.C. Chen 				pass++;
193594fdc2a8SY.C. Chen 				if (min_ddr_vref > ddr_vref)
193694fdc2a8SY.C. Chen 					min_ddr_vref = ddr_vref;
193794fdc2a8SY.C. Chen 				if (max_ddr_vref < ddr_vref)
193894fdc2a8SY.C. Chen 					max_ddr_vref = ddr_vref;
193994fdc2a8SY.C. Chen 			} else if (pass != 0)
194094fdc2a8SY.C. Chen 				break;
194194fdc2a8SY.C. Chen 		}
194294fdc2a8SY.C. Chen 	}
194394fdc2a8SY.C. Chen 
194494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
194594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
194694fdc2a8SY.C. Chen 	ddr_vref = (min_ddr_vref + max_ddr_vref + 1) >> 1;
194794fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
194894fdc2a8SY.C. Chen 
194994fdc2a8SY.C. Chen 	/* Wait DDR PHY init done */
195094fdc2a8SY.C. Chen 	ddr_phy_init_2500(ast);
195194fdc2a8SY.C. Chen 
195294fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
195394fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
195494fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
195594fdc2a8SY.C. Chen 
195694fdc2a8SY.C. Chen 	check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
195794fdc2a8SY.C. Chen 	enable_cache_2500(ast);
195894fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
195994fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
196094fdc2a8SY.C. Chen }
196194fdc2a8SY.C. Chen 
ast_dram_init_2500(struct ast_device * ast)196237b42cf9SThomas Zimmermann static bool ast_dram_init_2500(struct ast_device *ast)
196394fdc2a8SY.C. Chen {
196494fdc2a8SY.C. Chen 	u32 data;
196594fdc2a8SY.C. Chen 	u32 max_tries = 5;
196694fdc2a8SY.C. Chen 
196794fdc2a8SY.C. Chen 	do {
196894fdc2a8SY.C. Chen 		if (max_tries-- == 0)
196994fdc2a8SY.C. Chen 			return false;
197094fdc2a8SY.C. Chen 		set_mpll_2500(ast);
197194fdc2a8SY.C. Chen 		reset_mmc_2500(ast);
197294fdc2a8SY.C. Chen 		ddr_init_common_2500(ast);
197394fdc2a8SY.C. Chen 
197494fdc2a8SY.C. Chen 		data = ast_mindwm(ast, 0x1E6E2070);
197594fdc2a8SY.C. Chen 		if (data & 0x01000000)
197694fdc2a8SY.C. Chen 			ddr4_init_2500(ast, ast2500_ddr4_1600_timing_table);
197794fdc2a8SY.C. Chen 		else
197894fdc2a8SY.C. Chen 			ddr3_init_2500(ast, ast2500_ddr3_1600_timing_table);
197994fdc2a8SY.C. Chen 	} while (!ddr_test_2500(ast));
198094fdc2a8SY.C. Chen 
198194fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E2040, ast_mindwm(ast, 0x1E6E2040) | 0x41);
198294fdc2a8SY.C. Chen 
198394fdc2a8SY.C. Chen 	/* Patch code */
198494fdc2a8SY.C. Chen 	data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
198594fdc2a8SY.C. Chen 	ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
198694fdc2a8SY.C. Chen 
198794fdc2a8SY.C. Chen 	return true;
198894fdc2a8SY.C. Chen }
198994fdc2a8SY.C. Chen 
ast_patch_ahb_2500(struct ast_device * ast)199037b42cf9SThomas Zimmermann void ast_patch_ahb_2500(struct ast_device *ast)
1991f34bf652SKuoHsiang Chou {
1992f34bf652SKuoHsiang Chou 	u32	data;
1993f34bf652SKuoHsiang Chou 
1994f34bf652SKuoHsiang Chou 	/* Clear bus lock condition */
1995f34bf652SKuoHsiang Chou 	ast_moutdwm(ast, 0x1e600000, 0xAEED1A03);
1996f34bf652SKuoHsiang Chou 	ast_moutdwm(ast, 0x1e600084, 0x00010000);
1997f34bf652SKuoHsiang Chou 	ast_moutdwm(ast, 0x1e600088, 0x00000000);
1998f34bf652SKuoHsiang Chou 	ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
1999f34bf652SKuoHsiang Chou 	data = ast_mindwm(ast, 0x1e6e2070);
2000f34bf652SKuoHsiang Chou 	if (data & 0x08000000) {					/* check fast reset */
2001f34bf652SKuoHsiang Chou 		/*
2002f34bf652SKuoHsiang Chou 		 * If "Fast restet" is enabled for ARM-ICE debugger,
2003f34bf652SKuoHsiang Chou 		 * then WDT needs to enable, that
2004f34bf652SKuoHsiang Chou 		 * WDT04 is WDT#1 Reload reg.
2005f34bf652SKuoHsiang Chou 		 * WDT08 is WDT#1 counter restart reg to avoid system deadlock
2006f34bf652SKuoHsiang Chou 		 * WDT0C is WDT#1 control reg
2007f34bf652SKuoHsiang Chou 		 *	[6:5]:= 01:Full chip
2008f34bf652SKuoHsiang Chou 		 *	[4]:= 1:1MHz clock source
2009f34bf652SKuoHsiang Chou 		 *	[1]:= 1:WDT will be cleeared and disabled after timeout occurs
2010f34bf652SKuoHsiang Chou 		 *	[0]:= 1:WDT enable
2011f34bf652SKuoHsiang Chou 		 */
2012f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1E785004, 0x00000010);
2013f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1E785008, 0x00004755);
2014f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1E78500c, 0x00000033);
2015f34bf652SKuoHsiang Chou 		udelay(1000);
2016f34bf652SKuoHsiang Chou 	}
2017f34bf652SKuoHsiang Chou 	do {
2018f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
2019f34bf652SKuoHsiang Chou 		data = ast_mindwm(ast, 0x1e6e2000);
2020f34bf652SKuoHsiang Chou 	}	while (data != 1);
2021f34bf652SKuoHsiang Chou 	ast_moutdwm(ast, 0x1e6e207c, 0x08000000);	/* clear fast reset */
2022f34bf652SKuoHsiang Chou }
2023f34bf652SKuoHsiang Chou 
ast_post_chip_2500(struct drm_device * dev)202494fdc2a8SY.C. Chen void ast_post_chip_2500(struct drm_device *dev)
202594fdc2a8SY.C. Chen {
20265abaa683SThomas Zimmermann 	struct ast_device *ast = to_ast_device(dev);
202794fdc2a8SY.C. Chen 	u32 temp;
202894fdc2a8SY.C. Chen 	u8 reg;
202994fdc2a8SY.C. Chen 
203094fdc2a8SY.C. Chen 	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
2031f34bf652SKuoHsiang Chou 	if ((reg & AST_VRAM_INIT_STATUS_MASK) == 0) {/* vga only */
203294fdc2a8SY.C. Chen 		/* Clear bus lock condition */
2033f34bf652SKuoHsiang Chou 		ast_patch_ahb_2500(ast);
203494fdc2a8SY.C. Chen 
2035f34bf652SKuoHsiang Chou 		/* Disable watchdog */
2036f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1E78502C, 0x00000000);
2037f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1E78504C, 0x00000000);
2038f34bf652SKuoHsiang Chou 
2039f34bf652SKuoHsiang Chou 		/*
2040f34bf652SKuoHsiang Chou 		 * Reset USB port to patch USB unknown device issue
2041f34bf652SKuoHsiang Chou 		 * SCU90 is Multi-function Pin Control #5
2042f34bf652SKuoHsiang Chou 		 *	[29]:= 1:Enable USB2.0 Host port#1 (that the mutually shared USB2.0 Hub
2043f34bf652SKuoHsiang Chou 		 *				port).
2044f34bf652SKuoHsiang Chou 		 * SCU94 is Multi-function Pin Control #6
2045f34bf652SKuoHsiang Chou 		 *	[14:13]:= 1x:USB2.0 Host2 controller
2046f34bf652SKuoHsiang Chou 		 * SCU70 is Hardware Strap reg
2047f34bf652SKuoHsiang Chou 		 *	[23]:= 1:CLKIN is 25MHz and USBCK1 = 24/48 MHz (determined by
2048f34bf652SKuoHsiang Chou 		 *				[18]: 0(24)/1(48) MHz)
2049f34bf652SKuoHsiang Chou 		 * SCU7C is Write clear reg to SCU70
2050f34bf652SKuoHsiang Chou 		 *	[23]:= write 1 and then SCU70[23] will be clear as 0b.
2051f34bf652SKuoHsiang Chou 		 */
2052f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1E6E2090, 0x20000000);
2053f34bf652SKuoHsiang Chou 		ast_moutdwm(ast, 0x1E6E2094, 0x00004000);
2054f34bf652SKuoHsiang Chou 		if (ast_mindwm(ast, 0x1E6E2070) & 0x00800000) {
2055f34bf652SKuoHsiang Chou 			ast_moutdwm(ast, 0x1E6E207C, 0x00800000);
2056f34bf652SKuoHsiang Chou 			mdelay(100);
2057f34bf652SKuoHsiang Chou 			ast_moutdwm(ast, 0x1E6E2070, 0x00800000);
2058f34bf652SKuoHsiang Chou 		}
2059f34bf652SKuoHsiang Chou 		/* Modify eSPI reset pin */
2060f34bf652SKuoHsiang Chou 		temp = ast_mindwm(ast, 0x1E6E2070);
2061f34bf652SKuoHsiang Chou 		if (temp & 0x02000000)
2062f34bf652SKuoHsiang Chou 			ast_moutdwm(ast, 0x1E6E207C, 0x00004000);
206394fdc2a8SY.C. Chen 
206494fdc2a8SY.C. Chen 		/* Slow down CPU/AHB CLK in VGA only mode */
206594fdc2a8SY.C. Chen 		temp = ast_read32(ast, 0x12008);
206694fdc2a8SY.C. Chen 		temp |= 0x73;
206794fdc2a8SY.C. Chen 		ast_write32(ast, 0x12008, temp);
206894fdc2a8SY.C. Chen 
206994fdc2a8SY.C. Chen 		if (!ast_dram_init_2500(ast))
20701a19b4cbSThomas Zimmermann 			drm_err(dev, "DRAM init failed !\n");
207194fdc2a8SY.C. Chen 
207294fdc2a8SY.C. Chen 		temp = ast_mindwm(ast, 0x1e6e2040);
207394fdc2a8SY.C. Chen 		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
207494fdc2a8SY.C. Chen 	}
207594fdc2a8SY.C. Chen 
207694fdc2a8SY.C. Chen 	/* wait ready */
207794fdc2a8SY.C. Chen 	do {
207894fdc2a8SY.C. Chen 		reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
207994fdc2a8SY.C. Chen 	} while ((reg & 0x40) == 0);
208094fdc2a8SY.C. Chen }
2081