File Index
Files and directories
Sign in
FILE

ast_2500.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/ast/ast_2500.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright 2012 Red Hat Inc.
  4 *
  5 * Permission is hereby granted, free of charge, to any person obtaining a
  6 * copy of this software and associated documentation files (the
  7 * "Software"), to deal in the Software without restriction, including
  8 * without limitation the rights to use, copy, modify, merge, publish,
  9 * distribute, sub license, and/or sell copies of the Software, and to
 10 * permit persons to whom the Software is furnished to do so, subject to
 11 * the following conditions:
 12 *
 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 20 *
 21 * The above copyright notice and this permission notice (including the
 22 * next paragraph) shall be included in all copies or substantial portions
 23 * of the Software.
 24 */
 25/*
 26 * Authors: Dave Airlie <airlied@redhat.com>
 27 */
 28
 29#include <linux/delay.h>
 30#include <linux/pci.h>
 31
 32#include <drm/drm_drv.h>
 33#include <drm/drm_print.h>
 34
 35#include "ast_drv.h"
 36#include "ast_post.h"
 37
 38/*
 39 * POST
 40 */
 41
 42/*
 43 * AST2500 DRAM settings modules
 44 */
 45
 46#define REGTBL_NUM           17
 47#define REGIDX_010           0
 48#define REGIDX_014           1
 49#define REGIDX_018           2
 50#define REGIDX_020           3
 51#define REGIDX_024           4
 52#define REGIDX_02C           5
 53#define REGIDX_030           6
 54#define REGIDX_214           7
 55#define REGIDX_2E0           8
 56#define REGIDX_2E4           9
 57#define REGIDX_2E8           10
 58#define REGIDX_2EC           11
 59#define REGIDX_2F0           12
 60#define REGIDX_2F4           13
 61#define REGIDX_2F8           14
 62#define REGIDX_RFC           15
 63#define REGIDX_PLL           16
 64
 65static const u32 ast2500_ddr3_1600_timing_table[REGTBL_NUM] = {
 66	0x64604D38,		     /* 0x010 */
 67	0x29690599,		     /* 0x014 */
 68	0x00000300,		     /* 0x018 */
 69	0x00000000,		     /* 0x020 */
 70	0x00000000,		     /* 0x024 */
 71	0x02181E70,		     /* 0x02C */
 72	0x00000040,		     /* 0x030 */
 73	0x00000024,		     /* 0x214 */
 74	0x02001300,		     /* 0x2E0 */
 75	0x0E0000A0,		     /* 0x2E4 */
 76	0x000E001B,		     /* 0x2E8 */
 77	0x35B8C105,		     /* 0x2EC */
 78	0x08090408,		     /* 0x2F0 */
 79	0x9B000800,		     /* 0x2F4 */
 80	0x0E400A00,		     /* 0x2F8 */
 81	0x9971452F,		     /* tRFC  */
 82	0x000071C1		     /* PLL   */
 83};
 84
 85static const u32 ast2500_ddr4_1600_timing_table[REGTBL_NUM] = {
 86	0x63604E37,		     /* 0x010 */
 87	0xE97AFA99,		     /* 0x014 */
 88	0x00019000,		     /* 0x018 */
 89	0x08000000,		     /* 0x020 */
 90	0x00000400,		     /* 0x024 */
 91	0x00000410,		     /* 0x02C */
 92	0x00000101,		     /* 0x030 */
 93	0x00000024,		     /* 0x214 */
 94	0x03002900,		     /* 0x2E0 */
 95	0x0E0000A0,		     /* 0x2E4 */
 96	0x000E001C,		     /* 0x2E8 */
 97	0x35B8C106,		     /* 0x2EC */
 98	0x08080607,		     /* 0x2F0 */
 99	0x9B000900,		     /* 0x2F4 */
100	0x0E400A00,		     /* 0x2F8 */
101	0x99714545,		     /* tRFC  */
102	0x000071C1		     /* PLL   */
103};
104
105#define TIMEOUT              5000000
106
107void ast_2500_patch_ahb(void __iomem *regs)
108{
109	u32 data;
110
111	/* Clear bus lock condition */
112	__ast_moutdwm(regs, 0x1e600000, 0xAEED1A03);
113	__ast_moutdwm(regs, 0x1e600084, 0x00010000);
114	__ast_moutdwm(regs, 0x1e600088, 0x00000000);
115	__ast_moutdwm(regs, 0x1e6e2000, 0x1688A8A8);
116
117	data = __ast_mindwm(regs, 0x1e6e2070);
118	if (data & 0x08000000) { /* check fast reset */
119		/*
120		 * If "Fast restet" is enabled for ARM-ICE debugger,
121		 * then WDT needs to enable, that
122		 * WDT04 is WDT#1 Reload reg.
123		 * WDT08 is WDT#1 counter restart reg to avoid system deadlock
124		 * WDT0C is WDT#1 control reg
125		 *	[6:5]:= 01:Full chip
126		 *	[4]:= 1:1MHz clock source
127		 *	[1]:= 1:WDT will be cleeared and disabled after timeout occurs
128		 *	[0]:= 1:WDT enable
129		 */
130		__ast_moutdwm(regs, 0x1E785004, 0x00000010);
131		__ast_moutdwm(regs, 0x1E785008, 0x00004755);
132		__ast_moutdwm(regs, 0x1E78500c, 0x00000033);
133		udelay(1000);
134	}
135
136	do {
137		__ast_moutdwm(regs, 0x1e6e2000, 0x1688A8A8);
138		data = __ast_mindwm(regs, 0x1e6e2000);
139	} while (data != 1);
140
141	__ast_moutdwm(regs, 0x1e6e207c, 0x08000000); /* clear fast reset */
142}
143
144static bool mmc_test_single_2500(struct ast_device *ast, u32 datagen)
145{
146	return mmc_test(ast, datagen, 0x85);
147}
148
149static bool cbr_test_2500(struct ast_device *ast)
150{
151	ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
152	ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
153	if (!mmc_test_burst(ast, 0))
154		return false;
155	if (!mmc_test_single_2500(ast, 0))
156		return false;
157	return true;
158}
159
160static bool ddr_test_2500(struct ast_device *ast)
161{
162	ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
163	ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
164	if (!mmc_test_burst(ast, 0))
165		return false;
166	if (!mmc_test_burst(ast, 1))
167		return false;
168	if (!mmc_test_burst(ast, 2))
169		return false;
170	if (!mmc_test_burst(ast, 3))
171		return false;
172	if (!mmc_test_single_2500(ast, 0))
173		return false;
174	return true;
175}
176
177static void ddr_init_common_2500(struct ast_device *ast)
178{
179	ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
180	ast_moutdwm(ast, 0x1E6E0008, 0x2003000F);
181	ast_moutdwm(ast, 0x1E6E0038, 0x00000FFF);
182	ast_moutdwm(ast, 0x1E6E0040, 0x88448844);
183	ast_moutdwm(ast, 0x1E6E0044, 0x24422288);
184	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
185	ast_moutdwm(ast, 0x1E6E004C, 0x22222222);
186	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
187	ast_moutdwm(ast, 0x1E6E0208, 0x00000000);
188	ast_moutdwm(ast, 0x1E6E0218, 0x00000000);
189	ast_moutdwm(ast, 0x1E6E0220, 0x00000000);
190	ast_moutdwm(ast, 0x1E6E0228, 0x00000000);
191	ast_moutdwm(ast, 0x1E6E0230, 0x00000000);
192	ast_moutdwm(ast, 0x1E6E02A8, 0x00000000);
193	ast_moutdwm(ast, 0x1E6E02B0, 0x00000000);
194	ast_moutdwm(ast, 0x1E6E0240, 0x86000000);
195	ast_moutdwm(ast, 0x1E6E0244, 0x00008600);
196	ast_moutdwm(ast, 0x1E6E0248, 0x80000000);
197	ast_moutdwm(ast, 0x1E6E024C, 0x80808080);
198}
199
200static void ddr_phy_init_2500(struct ast_device *ast)
201{
202	u32 data, pass, timecnt;
203
204	pass = 0;
205	ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
206	while (!pass) {
207		for (timecnt = 0; timecnt < TIMEOUT; timecnt++) {
208			data = ast_mindwm(ast, 0x1E6E0060) & 0x1;
209			if (!data)
210				break;
211		}
212		if (timecnt != TIMEOUT) {
213			data = ast_mindwm(ast, 0x1E6E0300) & 0x000A0000;
214			if (!data)
215				pass = 1;
216		}
217		if (!pass) {
218			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
219			udelay(10); /* delay 10 us */
220			ast_moutdwm(ast, 0x1E6E0060, 0x00000005);
221		}
222	}
223
224	ast_moutdwm(ast, 0x1E6E0060, 0x00000006);
225}
226
227/*
228 * Check DRAM Size
229 * 1Gb : 0x80000000 ~ 0x87FFFFFF
230 * 2Gb : 0x80000000 ~ 0x8FFFFFFF
231 * 4Gb : 0x80000000 ~ 0x9FFFFFFF
232 * 8Gb : 0x80000000 ~ 0xBFFFFFFF
233 */
234static void check_dram_size_2500(struct ast_device *ast, u32 tRFC)
235{
236	u32 reg_04, reg_14;
237
238	reg_04 = ast_mindwm(ast, 0x1E6E0004) & 0xfffffffc;
239	reg_14 = ast_mindwm(ast, 0x1E6E0014) & 0xffffff00;
240
241	ast_moutdwm(ast, 0xA0100000, 0x41424344);
242	ast_moutdwm(ast, 0x90100000, 0x35363738);
243	ast_moutdwm(ast, 0x88100000, 0x292A2B2C);
244	ast_moutdwm(ast, 0x80100000, 0x1D1E1F10);
245
246	/* Check 8Gbit */
247	if (ast_mindwm(ast, 0xA0100000) == 0x41424344) {
248		reg_04 |= 0x03;
249		reg_14 |= (tRFC >> 24) & 0xFF;
250		/* Check 4Gbit */
251	} else if (ast_mindwm(ast, 0x90100000) == 0x35363738) {
252		reg_04 |= 0x02;
253		reg_14 |= (tRFC >> 16) & 0xFF;
254		/* Check 2Gbit */
255	} else if (ast_mindwm(ast, 0x88100000) == 0x292A2B2C) {
256		reg_04 |= 0x01;
257		reg_14 |= (tRFC >> 8) & 0xFF;
258	} else {
259		reg_14 |= tRFC & 0xFF;
260	}
261	ast_moutdwm(ast, 0x1E6E0004, reg_04);
262	ast_moutdwm(ast, 0x1E6E0014, reg_14);
263}
264
265static void enable_cache_2500(struct ast_device *ast)
266{
267	u32 reg_04, data;
268
269	reg_04 = ast_mindwm(ast, 0x1E6E0004);
270	ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x1000);
271
272	do
273		data = ast_mindwm(ast, 0x1E6E0004);
274	while (!(data & 0x80000));
275	ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
276}
277
278static void set_mpll_2500(struct ast_device *ast)
279{
280	u32 addr, data, param;
281
282	/* Reset MMC */
283	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
284	ast_moutdwm(ast, 0x1E6E0034, 0x00020080);
285	for (addr = 0x1e6e0004; addr < 0x1e6e0090;) {
286		ast_moutdwm(ast, addr, 0x0);
287		addr += 4;
288	}
289	ast_moutdwm(ast, 0x1E6E0034, 0x00020000);
290
291	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
292	data = ast_mindwm(ast, 0x1E6E2070) & 0x00800000;
293	if (data) {
294		/* CLKIN = 25MHz */
295		param = 0x930023E0;
296		ast_moutdwm(ast, 0x1E6E2160, 0x00011320);
297	} else {
298		/* CLKIN = 24MHz */
299		param = 0x93002400;
300	}
301	ast_moutdwm(ast, 0x1E6E2020, param);
302	udelay(100);
303}
304
305static void reset_mmc_2500(struct ast_device *ast)
306{
307	ast_moutdwm(ast, 0x1E78505C, 0x00000004);
308	ast_moutdwm(ast, 0x1E785044, 0x00000001);
309	ast_moutdwm(ast, 0x1E785048, 0x00004755);
310	ast_moutdwm(ast, 0x1E78504C, 0x00000013);
311	mdelay(100);
312	ast_moutdwm(ast, 0x1E785054, 0x00000077);
313	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
314}
315
316static void ddr3_init_2500(struct ast_device *ast, const u32 *ddr_table)
317{
318	ast_moutdwm(ast, 0x1E6E0004, 0x00000303);
319	ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
320	ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
321	ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
322	ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]);	     /* MODEREG4/6 */
323	ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]);	     /* MODEREG5 */
324	ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
325	ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]);	     /* MODEREG1/3 */
326
327	/* DDR PHY Setting */
328	ast_moutdwm(ast, 0x1E6E0200, 0x02492AAE);
329	ast_moutdwm(ast, 0x1E6E0204, 0x00001001);
330	ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
331	ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
332	ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
333	ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
334	ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
335	ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
336	ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
337	ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
338	ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
339	ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
340	ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
341	ast_moutdwm(ast, 0x1E6E02C0, 0x00000006);
342
343	/* Controller Setting */
344	ast_moutdwm(ast, 0x1E6E0034, 0x00020091);
345
346	/* Wait DDR PHY init done */
347	ddr_phy_init_2500(ast);
348
349	ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
350	ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
351	ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
352
353	check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
354	enable_cache_2500(ast);
355	ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
356	ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
357}
358
359static void ddr4_init_2500(struct ast_device *ast, const u32 *ddr_table)
360{
361	u32 data, data2, pass, retrycnt;
362	u32 ddr_vref, phy_vref;
363	u32 min_ddr_vref = 0, min_phy_vref = 0;
364	u32 max_ddr_vref = 0, max_phy_vref = 0;
365
366	ast_moutdwm(ast, 0x1E6E0004, 0x00000313);
367	ast_moutdwm(ast, 0x1E6E0010, ddr_table[REGIDX_010]);
368	ast_moutdwm(ast, 0x1E6E0014, ddr_table[REGIDX_014]);
369	ast_moutdwm(ast, 0x1E6E0018, ddr_table[REGIDX_018]);
370	ast_moutdwm(ast, 0x1E6E0020, ddr_table[REGIDX_020]);	     /* MODEREG4/6 */
371	ast_moutdwm(ast, 0x1E6E0024, ddr_table[REGIDX_024]);	     /* MODEREG5 */
372	ast_moutdwm(ast, 0x1E6E002C, ddr_table[REGIDX_02C] | 0x100); /* MODEREG0/2 */
373	ast_moutdwm(ast, 0x1E6E0030, ddr_table[REGIDX_030]);	     /* MODEREG1/3 */
374
375	/* DDR PHY Setting */
376	ast_moutdwm(ast, 0x1E6E0200, 0x42492AAE);
377	ast_moutdwm(ast, 0x1E6E0204, 0x09002000);
378	ast_moutdwm(ast, 0x1E6E020C, 0x55E00B0B);
379	ast_moutdwm(ast, 0x1E6E0210, 0x20000000);
380	ast_moutdwm(ast, 0x1E6E0214, ddr_table[REGIDX_214]);
381	ast_moutdwm(ast, 0x1E6E02E0, ddr_table[REGIDX_2E0]);
382	ast_moutdwm(ast, 0x1E6E02E4, ddr_table[REGIDX_2E4]);
383	ast_moutdwm(ast, 0x1E6E02E8, ddr_table[REGIDX_2E8]);
384	ast_moutdwm(ast, 0x1E6E02EC, ddr_table[REGIDX_2EC]);
385	ast_moutdwm(ast, 0x1E6E02F0, ddr_table[REGIDX_2F0]);
386	ast_moutdwm(ast, 0x1E6E02F4, ddr_table[REGIDX_2F4]);
387	ast_moutdwm(ast, 0x1E6E02F8, ddr_table[REGIDX_2F8]);
388	ast_moutdwm(ast, 0x1E6E0290, 0x00100008);
389	ast_moutdwm(ast, 0x1E6E02C4, 0x3C183C3C);
390	ast_moutdwm(ast, 0x1E6E02C8, 0x00631E0E);
391
392	/* Controller Setting */
393	ast_moutdwm(ast, 0x1E6E0034, 0x0001A991);
394
395	/* Train PHY Vref first */
396	pass = 0;
397
398	for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
399		max_phy_vref = 0x0;
400		pass = 0;
401		ast_moutdwm(ast, 0x1E6E02C0, 0x00001C06);
402		for (phy_vref = 0x40; phy_vref < 0x80; phy_vref++) {
403			ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
404			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
405			ast_moutdwm(ast, 0x1E6E02CC, phy_vref | (phy_vref << 8));
406			/* Fire DFI Init */
407			ddr_phy_init_2500(ast);
408			ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
409			if (cbr_test_2500(ast)) {
410				pass++;
411				data = ast_mindwm(ast, 0x1E6E03D0);
412				data2 = data >> 8;
413				data  = data & 0xff;
414				if (data > data2)
415					data = data2;
416				if (max_phy_vref < data) {
417					max_phy_vref = data;
418					min_phy_vref = phy_vref;
419				}
420			} else if (pass > 0) {
421				break;
422			}
423		}
424	}
425	ast_moutdwm(ast, 0x1E6E02CC, min_phy_vref | (min_phy_vref << 8));
426
427	/* Train DDR Vref next */
428	pass = 0;
429
430	for (retrycnt = 0; retrycnt < 4 && pass == 0; retrycnt++) {
431		min_ddr_vref = 0xFF;
432		max_ddr_vref = 0x0;
433		pass = 0;
434		for (ddr_vref = 0x00; ddr_vref < 0x40; ddr_vref++) {
435			ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
436			ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
437			ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
438			/* Fire DFI Init */
439			ddr_phy_init_2500(ast);
440			ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
441			if (cbr_test_2500(ast)) {
442				pass++;
443				if (min_ddr_vref > ddr_vref)
444					min_ddr_vref = ddr_vref;
445				if (max_ddr_vref < ddr_vref)
446					max_ddr_vref = ddr_vref;
447			} else if (pass != 0) {
448				break;
449			}
450		}
451	}
452
453	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
454	ast_moutdwm(ast, 0x1E6E0060, 0x00000000);
455	ddr_vref = (min_ddr_vref + max_ddr_vref + 1) >> 1;
456	ast_moutdwm(ast, 0x1E6E02C0, 0x00000006 | (ddr_vref << 8));
457
458	/* Wait DDR PHY init done */
459	ddr_phy_init_2500(ast);
460
461	ast_moutdwm(ast, 0x1E6E0120, ddr_table[REGIDX_PLL]);
462	ast_moutdwm(ast, 0x1E6E000C, 0x42AA5C81);
463	ast_moutdwm(ast, 0x1E6E0034, 0x0001AF93);
464
465	check_dram_size_2500(ast, ddr_table[REGIDX_RFC]);
466	enable_cache_2500(ast);
467	ast_moutdwm(ast, 0x1E6E001C, 0x00000008);
468	ast_moutdwm(ast, 0x1E6E0038, 0xFFFFFF00);
469}
470
471static bool ast_dram_init_2500(struct ast_device *ast)
472{
473	u32 data;
474	u32 max_tries = 5;
475
476	do {
477		if (max_tries-- == 0)
478			return false;
479		set_mpll_2500(ast);
480		reset_mmc_2500(ast);
481		ddr_init_common_2500(ast);
482
483		data = ast_mindwm(ast, 0x1E6E2070);
484		if (data & 0x01000000)
485			ddr4_init_2500(ast, ast2500_ddr4_1600_timing_table);
486		else
487			ddr3_init_2500(ast, ast2500_ddr3_1600_timing_table);
488	} while (!ddr_test_2500(ast));
489
490	ast_moutdwm(ast, 0x1E6E2040, ast_mindwm(ast, 0x1E6E2040) | 0x41);
491
492	/* Patch code */
493	data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
494	ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
495
496	return true;
497}
498
499static void ast_post_chip_2500(struct ast_device *ast)
500{
501	struct drm_device *dev = &ast->base;
502	u32 temp;
503	u8 reg;
504
505	reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
506	if ((reg & AST_IO_VGACRD0_VRAM_INIT_STATUS_MASK) == 0) {/* vga only */
507		/* Clear bus lock condition */
508		ast_2500_patch_ahb(ast->regs);
509
510		/* Disable watchdog */
511		ast_moutdwm(ast, 0x1E78502C, 0x00000000);
512		ast_moutdwm(ast, 0x1E78504C, 0x00000000);
513
514		/*
515		 * Reset USB port to patch USB unknown device issue
516		 * SCU90 is Multi-function Pin Control #5
517		 *	[29]:= 1:Enable USB2.0 Host port#1 (that the mutually shared USB2.0 Hub
518		 *				port).
519		 * SCU94 is Multi-function Pin Control #6
520		 *	[14:13]:= 1x:USB2.0 Host2 controller
521		 * SCU70 is Hardware Strap reg
522		 *	[23]:= 1:CLKIN is 25MHz and USBCK1 = 24/48 MHz (determined by
523		 *				[18]: 0(24)/1(48) MHz)
524		 * SCU7C is Write clear reg to SCU70
525		 *	[23]:= write 1 and then SCU70[23] will be clear as 0b.
526		 */
527		ast_moutdwm(ast, 0x1E6E2090, 0x20000000);
528		ast_moutdwm(ast, 0x1E6E2094, 0x00004000);
529		if (ast_mindwm(ast, 0x1E6E2070) & 0x00800000) {
530			ast_moutdwm(ast, 0x1E6E207C, 0x00800000);
531			mdelay(100);
532			ast_moutdwm(ast, 0x1E6E2070, 0x00800000);
533		}
534		/* Modify eSPI reset pin */
535		temp = ast_mindwm(ast, 0x1E6E2070);
536		if (temp & 0x02000000)
537			ast_moutdwm(ast, 0x1E6E207C, 0x00004000);
538
539		/* Slow down CPU/AHB CLK in VGA only mode */
540		temp = ast_read32(ast, 0x12008);
541		temp |= 0x73;
542		ast_write32(ast, 0x12008, temp);
543
544		if (!ast_dram_init_2500(ast))
545			drm_err(dev, "DRAM init failed !\n");
546
547		temp = ast_mindwm(ast, 0x1e6e2040);
548		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
549	}
550
551	/* wait ready */
552	do {
553		reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
554	} while ((reg & 0x40) == 0);
555}
556
557int ast_2500_post(struct ast_device *ast)
558{
559	ast_2300_set_def_ext_reg(ast);
560
561	if (ast->config_mode == ast_use_p2a) {
562		ast_post_chip_2500(ast);
563	} else {
564		if (ast->tx_chip == AST_TX_SIL164) {
565			/* Enable DVO */
566			ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80);
567		}
568	}
569
570	return 0;
571}
572
573/*
574 * Mode setting
575 */
576
577const struct ast_vbios_dclk_info ast_2500_dclk_table[] = {
578	{0x2c, 0xe7, 0x03},			/* 00: VCLK25_175	*/
579	{0x95, 0x62, 0x03},			/* 01: VCLK28_322	*/
580	{0x67, 0x63, 0x01},			/* 02: VCLK31_5		*/
581	{0x76, 0x63, 0x01},			/* 03: VCLK36		*/
582	{0xee, 0x67, 0x01},			/* 04: VCLK40		*/
583	{0x82, 0x62, 0x01},			/* 05: VCLK49_5		*/
584	{0xc6, 0x64, 0x01},			/* 06: VCLK50		*/
585	{0x94, 0x62, 0x01},			/* 07: VCLK56_25	*/
586	{0x80, 0x64, 0x00},			/* 08: VCLK65		*/
587	{0x7b, 0x63, 0x00},			/* 09: VCLK75		*/
588	{0x67, 0x62, 0x00},			/* 0a: VCLK78_75	*/
589	{0x7c, 0x62, 0x00},			/* 0b: VCLK94_5		*/
590	{0x8e, 0x62, 0x00},			/* 0c: VCLK108		*/
591	{0x85, 0x24, 0x00},			/* 0d: VCLK135		*/
592	{0x67, 0x22, 0x00},			/* 0e: VCLK157_5	*/
593	{0x6a, 0x22, 0x00},			/* 0f: VCLK162		*/
594	{0x4d, 0x4c, 0x80},			/* 10: VCLK154		*/
595	{0x68, 0x6f, 0x80},			/* 11: VCLK83.5		*/
596	{0x28, 0x49, 0x80},			/* 12: VCLK106.5	*/
597	{0x37, 0x49, 0x80},			/* 13: VCLK146.25	*/
598	{0x1f, 0x45, 0x80},			/* 14: VCLK148.5	*/
599	{0x47, 0x6c, 0x80},			/* 15: VCLK71		*/
600	{0x25, 0x65, 0x80},			/* 16: VCLK88.75	*/
601	{0x58, 0x01, 0x42},			/* 17: VCLK119		*/
602	{0x32, 0x67, 0x80},			/* 18: VCLK85_5		*/
603	{0x6a, 0x6d, 0x80},			/* 19: VCLK97_75	*/
604	{0x44, 0x20, 0x43},			/* 1a: VCLK118_25	*/
605};
606
607/*
608 * Device initialization
609 */
610
611static void ast_2500_detect_widescreen(struct ast_device *ast)
612{
613	if (__ast_2100_detect_wsxga_p(ast) || ast->chip == AST2510) {
614		ast->support_wsxga_p = true;
615		ast->support_fullhd = true;
616	}
617	if (__ast_2100_detect_wuxga(ast))
618		ast->support_wuxga = true;
619}
620
621static const struct ast_device_quirks ast_2500_device_quirks = {
622	.crtc_mem_req_threshold_low = 96,
623	.crtc_mem_req_threshold_high = 120,
624	.crtc_hsync_precatch_needed = true,
625};
626
627struct drm_device *ast_2500_device_create(struct pci_dev *pdev,
628					  const struct drm_driver *drv,
629					  enum ast_chip chip,
630					  enum ast_config_mode config_mode,
631					  void __iomem *regs,
632					  void __iomem *ioregs,
633					  bool need_post)
634{
635	struct drm_device *dev;
636	struct ast_device *ast;
637	int ret;
638
639	ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);
640	if (IS_ERR(ast))
641		return ERR_CAST(ast);
642	dev = &ast->base;
643
644	ast_device_init(ast, chip, config_mode, regs, ioregs, &ast_2500_device_quirks);
645
646	ast->dclk_table = ast_2500_dclk_table;
647
648	ast_2300_detect_tx_chip(ast);
649
650	if (need_post) {
651		ret = ast_post_gpu(ast);
652		if (ret)
653			return ERR_PTR(ret);
654	}
655
656	ret = ast_mm_init(ast);
657	if (ret)
658		return ERR_PTR(ret);
659
660	/* map reserved buffer */
661	ast->dp501_fw_buf = NULL;
662	if (ast->vram_size < pci_resource_len(pdev, 0)) {
663		ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0);
664		if (!ast->dp501_fw_buf)
665			drm_info(dev, "failed to map reserved buffer!\n");
666	}
667
668	ast_2500_detect_widescreen(ast);
669
670	ret = ast_mode_config_init(ast);
671	if (ret)
672		return ERR_PTR(ret);
673
674	return dev;
675}
~/ Read-only file preview.