changes from AMD for making OLPC video work.
[coreboot.git] / src / cpu / amd / model_gx2 / cpubug.c
1 #include <console/console.h>
2 #include <arch/io.h>
3 #include <stdint.h>
4 #include <device/device.h>
5 #include <device/pci.h>
6 #include <device/pci_ids.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <bitops.h>
10 #include <cpu/amd/gx2def.h>
11 #include <cpu/x86/msr.h>
12 #include <cpu/x86/cache.h>
13
14
15 #if 0
16 void
17 bug645(void){
18         msr_t msr;
19         rdmsr(CPU_ID_CONFIG);
20         msr.whatever |= ID_CONFIG_SERIAL_SET;
21         wrmsr(msr);
22 }
23
24 void
25 bug573(void){
26         msr_t msr;
27
28         msr = rdmsr(MC_GLD_MSR_PM);
29         msr.eax &= 0xfff3;
30         wrmsr(MC_GLD_MSR_PM);
31 }
32 #endif
33
34 /**************************************************************************
35  *
36  *      pcideadlock
37  *
38  *      Bugtool #465 and #609
39  *      PCI cache deadlock
40  *      There is also fix code in cache and PCI functions. This bug is very is pervasive.
41  *
42  *      Entry:
43  *      Exit:
44  *      Modified:
45  *
46  **************************************************************************/
47 static void
48 pcideadlock(void)
49 {
50         msr_t msr;
51
52         /*
53          * forces serialization of all load misses. Setting this bit prevents the 
54          * DM pipe from backing up if a read request has to be held up waiting 
55          * for PCI writes to complete.
56         */
57         msr = rdmsr(CPU_DM_CONFIG0);
58         msr.hi &= ~(7<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
59         msr.hi |= (2<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
60         msr.lo |= DM_CONFIG0_LOWER_MISSER_SET;
61         wrmsr(CPU_DM_CONFIG0, msr);
62
63         /* interlock instruction fetches to WS regions with data accesses.
64          * This prevents an instruction fetch from going out to PCI if the 
65          * data side is about to make a request.
66          */
67         msr = rdmsr(CPU_IM_CONFIG);
68         msr.lo |= IM_CONFIG_LOWER_QWT_SET;
69         wrmsr(CPU_IM_CONFIG, msr);
70         
71         /* write serialize memory hole to PCI. Need to unWS when something is 
72          * shadowed regardless of cachablility.
73          */
74         msr.lo = 0x021212121;
75         msr.hi = 0x021212121;
76         wrmsr( CPU_RCONF_A0_BF, msr);
77         wrmsr( CPU_RCONF_C0_DF, msr);
78         wrmsr( CPU_RCONF_E0_FF, msr);
79 }
80
81 /**************************************************************************** 
82  *
83  *      CPUbug784
84  *
85  *      Bugtool #784 + #792
86  *
87  *      Fix CPUID instructions for < 3.0 CPUs
88  *
89  *      Entry:
90  *      Exit:
91  *      Modified:
92  *
93 /****************************************************************************/
94
95 void bug784(void)
96 {
97         msr_t msr;
98         //static char *name = "Geode by NSC";
99
100         /* we'll do this the stupid way, for now, but that's the string they want. NO ONE KNOWS why you
101          * would do this -- the OS can figure this type of stuff out!
102          */
103         msr = rdmsr(0x3006);
104         msr.hi = 0x646f6547;
105         wrmsr(0x3006, msr);
106
107         msr = rdmsr(0x3007);
108         msr.hi = 0x79622065;
109         msr.lo = 0x43534e20;
110         wrmsr(0x3007, msr);
111
112         msr = rdmsr(0x3002);
113         wrmsr(0x3008, msr);
114
115         /* More CPUID to match AMD better. #792*/
116         msr = rdmsr(0x3009);
117         msr.hi = 0x0C0C0A13D;
118         msr.lo = 0x00000000;
119         wrmsr(0x3009, msr);
120 }
121
122 /* cpubug 1398: enable MC if we KNOW we have DDR*/
123 /**************************************************************************
124  *
125  *      CPUbugIAENG1398
126  *
127  *      ClearQuest #IAENG1398
128  *      The MC can not be enabled with SDR memory but can for DDR. Enable for
129  *      DDR here if the setup token is "Default"
130  *      Add this back to core by default once 2.0 CPUs are not supported.
131  *      Entry:
132  *      Exit:
133  *      Modified:
134  *
135  **************************************************************************/
136 void eng1398(void)
137 {
138         msr_t msr;
139
140         msr = rdmsr(MSR_GLCP+0x17);
141         if ((msr.lo & 0xff) <= CPU_REV_2_0) {
142                 msr = rdmsr(GLCP_SYS_RSTPLL);
143                 if (msr.lo & (1<<RSTPPL_LOWER_SDRMODE_SHIFT))
144                         return;
145         }
146
147         /* no CMOS/NVRAM to check, so enable MC Clock Gating */
148         msr = rdmsr(MC_GLD_MSR_PM);
149         msr.lo |= 3; /* enable MC clock gating.*/
150         wrmsr(MC_GLD_MSR_PM, msr);
151 }
152
153 void
154 eng2900(void){
155         printk_err(" NOT DOING eng2900: only shown to be a windows problem\n");
156 #if 0
157
158 ;**************************************************************************
159 ;*
160 ;*      CPUbugIAENG2900
161 ;*
162 ;*      Clear Quest IAENG00002900, VSS 118.150
163 ;*
164 ;*      BTB issue causes blue screen in windows.
165 ;*
166 ;*      Entry:
167 ;*      Exit:
168 ;*      Modified:
169 ;*
170 ;**************************************************************************
171 CPUbugIAENG2900 PROC NEAR PUBLIC
172         pushad
173
174 ; Clear bit 43, disables the sysenter/sysexit in CPUID3
175         mov     ecx, 3003h
176         RDMSR
177         and     edx, 0FFFFF7FFh
178         WRMSR
179
180         mov     cx, TOKEN_BTB_2900_SWAPSIF_ENABLE
181         NOSTACK bx, GetNVRAMValueBX
182         cmp     ax, TVALUE_ENABLE
183         jne     bug2900exit
184
185
186 ;Disable enable_actions in DIAGCTL while setting up GLCP
187         mov     ecx, MSR_GLCP + 005fh
188         xor     edx, edx
189         xor     eax, eax
190         WRMSR
191
192 ;Changing DBGCLKCTL register to GeodeLink
193         mov     ecx, MSR_GLCP + 0016h
194         xor     edx, edx
195         xor     eax, eax
196         WRMSR
197
198         mov     ecx, MSR_GLCP + 0016h
199         xor     edx, edx
200         mov     eax, 02h
201         WRMSR
202
203 ;The code below sets up the RedCloud to stall for 4 GeodeLink clocks when CPU is snooped.
204 ;Because setting XSTATE to 0 overrides any other XSTATE action, the code will always
205 ;stall for 4 GeodeLink clocks after a snoop request goes away even if it occured a clock or two 
206 ;later than a different snoop; the stall signal will never 'glitch high' for 
207 ;only one or two CPU clocks with this code.
208
209 ;Send mb0 port 3 requests to upper GeodeLink diag bits [63:32]
210         mov     ecx, MSR_GLIU0 + 2005h
211         xor     edx, edx
212         mov     eax, 80338041h
213         WRMSR
214
215 ;set5m watches request ready from mb0 to CPU (snoop)
216         mov     ecx, MSR_GLCP + 0045h
217         mov     edx, 5ad68000h
218         xor     eax, eax
219         WRMSR
220
221 ;SET4M will be high when state is idle (XSTATE=11)
222         mov     ecx, MSR_GLCP + 0044h
223         xor     edx, edx
224         mov     eax, 0140h
225         WRMSR
226
227 ;SET5n to watch for processor stalled state
228         mov     ecx, MSR_GLCP + 004Dh
229         mov     edx, 2000h
230         xor     eax, eax
231         WRMSR
232
233 ;Writing action number 13: XSTATE=0 to occur when CPU is snooped unless we're stalled
234         mov     ecx, MSR_GLCP + 0075h
235         xor     edx, edx
236         mov     eax, 00400000h
237         WRMSR
238
239 ;Writing action number 11: inc XSTATE every GeodeLink clock unless we're idle
240         mov     ecx, MSR_GLCP + 0073h
241         xor     edx, edx
242         mov     eax, 30000h
243         WRMSR
244
245
246 ;Writing action number 5: STALL_CPU_PIPE when exitting idle state or not in idle state
247         mov     ecx, MSR_GLCP + 006Dh
248         xor     edx, edx
249         mov     eax, 00430000h
250         WRMSR
251
252 ;Writing DIAGCTL Register to enable the stall action and to let set5m watch the upper GeodeLink diag bits.
253         mov     ecx, MSR_GLCP + 005fh
254         xor     edx, edx
255         mov     eax, 80004000h
256         WRMSR
257
258
259 bug2900exit:
260         popad
261         ret
262 CPUbugIAENG2900 ENDP
263 #endif
264 }
265
266 void bug118253(void)
267 {
268         /* GLPCI PIO Post Control shouldn't be enabled */
269         msr_t msr;
270
271         msr = rdmsr(GLPCI_SPARE);
272         msr.lo &= ~GLPCI_SPARE_LOWER_PPC_SET;
273         wrmsr(GLPCI_SPARE, msr);
274 }
275
276 void bug118339(void)
277 {
278         /* per AMD, do this always */
279         msr_t msr = {0,0};
280         int msrnum;
281
282         /* Disable enable_actions in DIAGCTL while setting up GLCP */
283         wrmsr(MSR_GLCP + 0x005f, msr);
284
285         /*  SET2M fires if VG pri is odd (3, not 2) and Ystate=0 */
286         msrnum =  MSR_GLCP + 0x042;
287         /*      msr.hi =  2d6b8000h */;
288         msr.hi =  0x596b8000;
289         msr.lo =  0x00000a00;
290         wrmsr(msrnum, msr);
291
292         /*  SET3M fires if MBUS changed and VG pri is odd */
293         msrnum =  MSR_GLCP + 0x043;
294         msr.hi =  0x596b8040;
295         msr.lo = 0;
296         wrmsr(msrnum, msr);
297
298         /*  Put VG request data on lower diag bus */
299         msrnum =  MSR_GLIU0 + 0x2005;
300         msr.hi = 0;
301         msr.lo =  0x80338041;
302         wrmsr(msrnum, msr);
303
304         /*  Increment Y state if SET3M if true */
305         msrnum =  MSR_GLCP + 0x074;
306         msr.hi = 0;
307         msr.lo =  0x0000c000;
308         wrmsr(msrnum, msr);
309
310         /*  Set up MBUS action to PRI=3 read of MBIU */
311         msrnum =  MSR_GLCP + 0x020;
312         msr.hi =  0x0000d863;
313         msr.lo =  0x20002000;
314         wrmsr(msrnum, msr);
315
316         /*  Trigger MBUS action if VG=pri3 and Y=0, this blocks most PCI */
317         msrnum =  MSR_GLCP + 0x071;
318         msr.hi = 0;
319         msr.lo =  0x00000c00;
320         wrmsr(msrnum, msr);
321
322         /* Writing DIAGCTL */
323         msrnum =  MSR_GLCP + 0x005f;
324         msr.hi = 0;
325         msr.lo =  0x80004000;
326         wrmsr(msrnum, msr);
327
328         /*  Code to enable FS2 even when BTB and VGTEAR SWAPSiFs are enabled */
329         /*  As per Todd Roberts in PBz1094 and PBz1095 */
330         /*  Moved from CPUREG to CPUBUG per Tom Sylla */
331         msrnum =  0x04C000042;          /*  GLCP SETMCTL Register */;
332         msr = rdmsr(msrnum);
333         msr.hi |= 8;                    /*  Bit 35 = MCP_IN */
334         wrmsr(msrnum, msr);
335 }
336
337
338
339 /****************************************************************************/
340 /***/
341 /**     DisableMemoryReorder*/
342 /***/
343 /**     PBZ 3659:*/
344 /**      The MC reordered transactions incorrectly and breaks coherency.*/
345 /**      Disable reording and take a potential performance hit.*/
346 /**      This is safe to do here and not in MC init since there is nothing*/
347 /**      to maintain coherency with and the cache is not enabled yet.*/
348 /***/
349 /***/
350 /**     Entry:*/
351 /**     Exit:*/
352 /**     Modified:*/
353 /***/
354 /****************************************************************************/
355 void disablememoryreadorder(void)
356 {       
357         msr_t msr;
358         msr = rdmsr(MC_CF8F_DATA);
359
360         msr.hi |=  CF8F_UPPER_REORDER_DIS_SET;
361         wrmsr(MC_CF8F_DATA, msr);
362 }
363
364 void
365 cpubug(void)
366 {
367         msr_t msr;
368         int rev;
369
370         msr = rdmsr(GLCP_CHIP_REVID);
371
372         rev = msr.lo & 0xff;
373         if (rev < 0x20) {
374                 printk_err("%s: rev < 0x20! bailing!\n");
375                 return;
376         }
377         printk_debug("Doing cpubug fixes for rev 0x%x\n", rev);
378         switch(rev)
379         {
380                 case 0x20:
381                         pcideadlock();
382                         eng1398();
383                         /* cs 5530 bug; ignore 
384                         bug752();
385                         */
386                         break;
387                 case 0x21:
388                         pcideadlock();
389                         eng1398();
390                         eng2900();
391                         bug118339();
392                         break;
393                 case 0x22:
394                 case 0x30: 
395                         break;
396                 default:
397                         printk_err("unknown rev %x, bailing\n", rev);
398                         return;
399         }
400         bug784();
401         bug118253();
402         disablememoryreadorder();
403         printk_debug("Done cpubug fixes \n");
404 }