summaryrefslogtreecommitdiff
path: root/src/cpu/amd/model_gx2/cpubug.c
blob: 34ebdc92853506f713535ebf042b1477db99d319 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
#include <console/console.h>
#include <arch/io.h>
#include <stdint.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <stdlib.h>
#include <string.h>
#include <bitops.h>
#include <cpu/amd/gx2def.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/cache.h>


#if 0
void
bug645(void){
	msr_t msr;
	rdmsr(CPU_ID_CONFIG);
	msr.whatever |= ID_CONFIG_SERIAL_SET;
	wrmsr(msr);
}

void
bug573(void){
	msr_t msr;

	msr = rdmsr(MC_GLD_MSR_PM);
	msr.eax &= 0xfff3;
	wrmsr(MC_GLD_MSR_PM);
}
#endif

static void
pcideadlock(void){
	msr_t msr;

	msr = rdmsr(CPU_DM_CONFIG0);
	msr.hi &= ~(7<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
	msr.hi |= (2<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
	msr.lo |= DM_CONFIG0_LOWER_MISSER_SET;
	wrmsr(CPU_DM_CONFIG0, msr);



	msr = rdmsr(CPU_IM_CONFIG);
	msr.lo |= IM_CONFIG_LOWER_QWT_SET;	/* interlock instruction fetches to WS regions with data accesses.
									  * This prevents in instruction fetch from going out to PCI if the 
									  * data side is about to make a request.
									  */
	wrmsr(CPU_IM_CONFIG, msr);
	/* write serialize memory hole to PCI. Need to to unWS when something is shadowed regardless of cachablility.*/

	msr.lo = 0x021212121;
	msr.hi = 0x021212121;
	wrmsr( CPU_RCONF_A0_BF, msr);
	wrmsr( CPU_RCONF_C0_DF, msr);
	wrmsr( CPU_RCONF_E0_FF, msr);
}

/****************************************************************************/
/***/
/**	CPUbug784*/
/***/
/**	Bugtool #784 + #792*/
/***/
/**	Fix CPUID instructions for < 3.0 CPUs*/
/***/
/**	Entry:*/
/**	Exit:*/
/**	Modified:*/
/***/
/****************************************************************************/

void bug784(void){
	msr_t msr;
//	static char *name = "Geode by NSC";

	/* we'll do this the stupid way, for now, but that's the string they want. NO ONE KNOWS why you
	  * would do this -- the OS can figure this type of stuff out!
	  */
	msr = rdmsr(0x3006);
	msr.hi = 0x646f6547;
	wrmsr(0x3006, msr);

	msr = rdmsr(0x3007);
	msr.hi = 0x79622065;
	msr.lo = 0x43534e20;
	wrmsr(0x3007, msr);

	msr = rdmsr(0x3002);
	wrmsr(0x3008, msr);

/* More CPUID to match AMD better. #792*/
	msr = rdmsr(0x3009);
	msr.hi = 0x0C0C0A13D;
	msr.lo = 0x00000000;
	wrmsr(0x3009, msr);
}

/* cpubug 1398: enable MC if we KNOW we have DDR*/
void
eng1398(void){
	msr_t msr;

	msr = rdmsr(MSR_GLCP+0x17);
	if ((msr.lo & 0xff) < CPU_REV_2_0) {
		msr = rdmsr(GLCP_SYS_RSTPLL);
		if (msr.lo & (1<<RSTPPL_LOWER_SDRMODE_SHIFT))
			return;
	}

	/* no bios to check, we just go for it? */
	msr = rdmsr(MC_GLD_MSR_PM);
	msr.lo |= 3; /* enable MC clock gating.*/
	wrmsr(MC_GLD_MSR_PM, msr);
}

void
eng2900(void){
	printk_err(" NOT DOING eng2900: only shown to be a windows problem\n");
#if 0

;**************************************************************************
;*
;*	CPUbugIAENG2900
;*
;*	Clear Quest IAENG00002900, VSS 118.150
;*
;*	BTB issue causes blue screen in windows.
;*
;*	Entry:
;*	Exit:
;*	Modified:
;*
;**************************************************************************
CPUbugIAENG2900	PROC NEAR PUBLIC
	pushad

; Clear bit 43, disables the sysenter/sysexit in CPUID3
	mov	ecx, 3003h
	RDMSR
	and	edx, 0FFFFF7FFh
	WRMSR

	mov	cx, TOKEN_BTB_2900_SWAPSIF_ENABLE
	NOSTACK	bx, GetNVRAMValueBX
	cmp	ax, TVALUE_ENABLE
	jne	bug2900exit


;Disable enable_actions in DIAGCTL while setting up GLCP
	mov	ecx, MSR_GLCP + 005fh
	xor	edx, edx
	xor	eax, eax
	WRMSR

;Changing DBGCLKCTL register to GeodeLink
	mov	ecx, MSR_GLCP + 0016h
	xor	edx, edx
	xor	eax, eax
	WRMSR

	mov	ecx, MSR_GLCP + 0016h
	xor	edx, edx
	mov	eax, 02h
	WRMSR

;The code below sets up the RedCloud to stall for 4 GeodeLink clocks when CPU is snooped.
;Because setting XSTATE to 0 overrides any other XSTATE action, the code will always
;stall for 4 GeodeLink clocks after a snoop request goes away even if it occured a clock or two 
;later than a different snoop; the stall signal will never 'glitch high' for 
;only one or two CPU clocks with this code.

;Send mb0 port 3 requests to upper GeodeLink diag bits [63:32]
	mov	ecx, MSR_GLIU0 + 2005h
	xor	edx, edx
	mov	eax, 80338041h
	WRMSR

;set5m watches request ready from mb0 to CPU (snoop)
	mov	ecx, MSR_GLCP + 0045h
	mov	edx, 5ad68000h
	xor	eax, eax
	WRMSR

;SET4M will be high when state is idle (XSTATE=11)
	mov	ecx, MSR_GLCP + 0044h
	xor	edx, edx
	mov	eax, 0140h
	WRMSR

;SET5n to watch for processor stalled state
	mov	ecx, MSR_GLCP + 004Dh
	mov	edx, 2000h
	xor	eax, eax
	WRMSR

;Writing action number 13: XSTATE=0 to occur when CPU is snooped unless we're stalled
	mov	ecx, MSR_GLCP + 0075h
	xor	edx, edx
	mov	eax, 00400000h
	WRMSR

;Writing action number 11: inc XSTATE every GeodeLink clock unless we're idle
	mov	ecx, MSR_GLCP + 0073h
	xor	edx, edx
	mov	eax, 30000h
	WRMSR


;Writing action number 5: STALL_CPU_PIPE when exitting idle state or not in idle state
	mov	ecx, MSR_GLCP + 006Dh
	xor	edx, edx
	mov	eax, 00430000h
	WRMSR

;Writing DIAGCTL Register to enable the stall action and to let set5m watch the upper GeodeLink diag bits.
	mov	ecx, MSR_GLCP + 005fh
	xor	edx, edx
	mov	eax, 80004000h
	WRMSR


bug2900exit:
	popad
	ret
CPUbugIAENG2900	ENDP
#endif
}

void bug118253(void){
	msr_t msr;

	msr = rdmsr(GLPCI_SPARE);
	msr.lo &= ~GLPCI_SPARE_LOWER_PPC_SET;
	wrmsr(GLPCI_SPARE, msr);
}

void
bug118339(void) {
	printk_err("This is OPTIONAL BIOS-ENABLED ... ignore for now\n");
#if 0
	PROC NEAR PUBLIC
	pushad

	mov	cx, TOKEN_VGTEAR_118339_SWAPSIF_ENABLE
	NOSTACK	bx, GetNVRAMValueBX
	cmp	ax, TVALUE_ENABLE
	jne	bug118339exit

;Disable enable_actions in DIAGCTL while setting up GLCP
	mov	ecx, MSR_GLCP + 005fh
	xor	edx, edx
	xor	eax, eax
	WRMSR

; SET2M fires if VG pri is odd (3, not 2) and Ystate=0
	mov	ecx, MSR_GLCP + 042h
;	mov	edx, 2d6b8000h
	mov	edx, 596b8000h
	mov	eax, 00000a00h
	WRMSR

; SET3M fires if MBUS changed and VG pri is odd
	mov	ecx, MSR_GLCP + 043h
	mov	edx, 596b8040h
	xor	eax, eax
	WRMSR

; Put VG request data on lower diag bus
	mov	ecx, MSR_GLIU0 + 2005h
	xor	edx, edx
	mov	eax, 80338041h
	WRMSR

; Increment Y state if SET3M if true
	mov	ecx, MSR_GLCP + 074h
	xor	edx, edx
	mov	eax, 0000c000h
	WRMSR

; Set up MBUS action to PRI=3 read of MBIU
	mov	ecx, MSR_GLCP + 020h
	mov	edx, 0000d863h
	mov	eax, 20002000h
	WRMSR

; Trigger MBUS action if VG=pri3 and Y=0, this blocks most PCI
	mov	ecx, MSR_GLCP + 071h
	xor	edx, edx
	mov	eax, 00000c00h
	WRMSR

;Writing DIAGCTL
	mov	ecx, MSR_GLCP + 005fh
	xor	edx, edx
	mov	eax, 80004000h
	WRMSR

	; Code to enable FS2 even when BTB and VGTEAR SWAPSiFs are enabled
	; As per Todd Roberts in PBz1094 and PBz1095
	; Moved from CPUREG to CPUBUG per Tom Sylla
	mov	ecx, 04C000042h	; GLCP SETMCTL Register
	rdmsr
	or	edx, 8			; Bit 35 = MCP_IN
	wrmsr
	
bug118339exit:
	popad
	ret
CPUbug118339	ENDP
#endif
}



/****************************************************************************/
/***/
/**	DisableMemoryReorder*/
/***/
/**	PBZ 3659:*/
/**	 The MC reordered transactions incorrectly and breaks coherency.*/
/**	 Disable reording and take a potential performance hit.*/
/**	 This is safe to do here and not in MC init since there is nothing*/
/**	 to maintain coherency with and the cache is not enabled yet.*/
/***/
/***/
/**	Entry:*/
/**	Exit:*/
/**	Modified:*/
/***/
/****************************************************************************/
void
disablememoryreadorder(void) {	
	msr_t msr;
	msr = rdmsr(MC_CF8F_DATA);

	msr.hi |=  CF8F_UPPER_REORDER_DIS_SET;
	wrmsr(MC_CF8F_DATA, msr);
}
void
cpubug(void){
	msr_t msr;
	int rev;

	msr = rdmsr(GLCP_CHIP_REVID);

	rev = msr.lo & 0xff;
	if (rev < 0x20) {
		printk_err("%s: rev < 0x20! bailing!\n");
		return;
	}
	printk_debug("Doing cpubug fixes for rev 0x%x\n", rev);
	switch(rev)
	{
		case 0x20:
			pcideadlock();
			eng1398();
			/* cs 5530 bug; ignore 
			bug752();
			*/
			break;
		case 0x21:
			pcideadlock();
			eng1398();
			eng2900();
			bug118339();
			break;
		case 0x22:
		case 0x30: 
			break;
		default:
			printk_err("unknown rev %x, bailing\n", rev);
			return;
	}
	bug784();
	bug118253();
	disablememoryreadorder();
	printk_debug("Done cpubug fixes \n");
}