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