67f546d297d453bfeb8240cd0832944a8712c689
[coreboot.git] / src / northbridge / amd / amdmct / mct / mct_d_gcc.h
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20
21 static inline void _WRMSR(u32 addr, u32 lo, u32 hi)
22 {
23         __asm__ volatile (
24                 "wrmsr"
25                 :
26                 :"c"(addr),"a"(lo), "d" (hi)
27                 );
28 }
29
30
31 static inline void _RDMSR(u32 addr, u32 *lo, u32 *hi)
32 {
33         __asm__ volatile (
34                 "rdmsr"
35                 :"=a"(*lo), "=d" (*hi)
36                 :"c"(addr)
37                 );
38 }
39
40
41 static inline void _RDTSC(u32 *lo, u32 *hi)
42 {
43         __asm__ volatile (
44                  "rdtsc"
45                  : "=a" (*lo), "=d"(*hi)
46                  );
47 }
48
49
50 static inline void _cpu_id(u32 addr, u32 *val)
51 {
52         __asm__ volatile(
53                  "cpuid"
54                  : "=a" (val[0]),
55                    "=b" (val[1]),
56                    "=c" (val[2]),
57                    "=d" (val[3])
58                  : "0" (addr));
59
60 }
61
62
63 static inline u32 bsr(u32 x)
64 {
65         u8 i;
66         u32 ret = 0;
67
68         for(i=31; i>0; i--) {
69                 if(x & (1<<i)) {
70                         ret = i;
71                         break;
72                 }
73         }
74
75         return ret;
76
77 }
78
79
80 static inline u32 bsf(u32 x)
81 {
82         u8 i;
83         u32 ret = 32;
84
85         for(i=0; i<32; i++) {
86                 if(x & (1<<i)) {
87                         ret = i;
88                         break;
89                 }
90         }
91
92         return ret;
93 }
94
95 #define _MFENCE asm volatile ( "mfence")
96
97 #define _SFENCE asm volatile ( "sfence" )
98
99 /* prevent speculative execution of following instructions */
100 #define _EXECFENCE asm volatile ("outb %al, $0xed")
101
102 static inline u32 read_cr4(void)
103 {
104         u32 cr4;
105         __asm__ volatile ("movl %%cr4, %0" : "=r" (cr4));
106         return cr4;
107 }
108
109
110 static inline void write_cr4(u32 cr4)
111 {
112         __asm__ volatile ("movl %0, %%cr4" : : "r" (cr4));
113 }
114
115
116 u32 SetUpperFSbase(u32 addr_hi);
117
118
119 static void proc_CLFLUSH(u32 addr_hi)
120 {
121         SetUpperFSbase(addr_hi);
122
123         __asm__ volatile (
124                 /* clflush fs:[eax] */
125                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
126                  "clflush %%fs:(%0)\n\t"
127                 "mfence\n\t"
128                  ::"a" (addr_hi<<8)
129         );
130 }
131
132
133 static void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num)
134 {
135         __asm__ volatile (
136                 /*prevent speculative execution of following instructions*/
137                 /* FIXME: needed ? */
138                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
139                 "1:\n\t"
140                 "movdqa (%3), %%xmm0\n\t"
141                 "movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
142                 "addl %1, %0\n\t"
143                 "addl %1, %3\n\t"
144                 "loop 1b\n\t"
145                 "mfence\n\t"
146
147                  :: "a" (addr_lo), "d" (16), "c" (line_num * 4), "b"(buf_a)
148         );
149
150 }
151
152
153 u32 read32_fs(u32 addr_lo)
154 {
155         u32 value;
156         __asm__ volatile (
157                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
158                 "movl %%fs:(%1), %0\n\t"
159                 :"=b"(value): "a" (addr_lo)
160         );
161         return value;
162 }
163
164
165 u8 read8_fs(u32 addr_lo)
166 {
167         u8 byte;
168         __asm__ volatile (
169                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
170                 "movb %%fs:(%1), %b0\n\t"
171                 "mfence\n\t"
172                 :"=b"(byte): "a" (addr_lo)
173         );
174         return byte;
175 }
176
177
178 static void FlushDQSTestPattern_L9(u32 addr_lo)
179 {
180         __asm__ volatile (
181                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
182                 "clflush %%fs:-128(%%ecx)\n\t"
183                 "clflush %%fs:-64(%%ecx)\n\t"
184                 "clflush %%fs:(%%ecx)\n\t"
185                 "clflush %%fs:64(%%ecx)\n\t"
186
187                 "clflush %%fs:-128(%%eax)\n\t"
188                 "clflush %%fs:-64(%%eax)\n\t"
189                 "clflush %%fs:(%%eax)\n\t"
190                 "clflush %%fs:64(%%eax)\n\t"
191
192                 "clflush %%fs:-128(%%ebx)\n\t"
193
194                  ::  "b" (addr_lo+128+8*64), "c"(addr_lo+128),
195                      "a"(addr_lo+128+4*64)
196         );
197
198 }
199
200
201 static __attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo)
202 {
203         __asm__ volatile (
204                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
205                 "clflush %%fs:-128(%%eax)\n\t"
206                 "clflush %%fs:-64(%%eax)\n\t"
207                 "clflush %%fs:(%%eax)\n\t"
208                 "clflush %%fs:64(%%eax)\n\t"
209
210                 "clflush %%fs:-128(%%edi)\n\t"
211                 "clflush %%fs:-64(%%edi)\n\t"
212                 "clflush %%fs:(%%edi)\n\t"
213                 "clflush %%fs:64(%%edi)\n\t"
214
215                 "clflush %%fs:-128(%%ebx)\n\t"
216                 "clflush %%fs:-64(%%ebx)\n\t"
217                 "clflush %%fs:(%%ebx)\n\t"
218                 "clflush %%fs:64(%%ebx)\n\t"
219
220                 "clflush %%fs:-128(%%ecx)\n\t"
221                 "clflush %%fs:-64(%%ecx)\n\t"
222                 "clflush %%fs:(%%ecx)\n\t"
223                 "clflush %%fs:64(%%ecx)\n\t"
224
225                 "clflush %%fs:-128(%%edx)\n\t"
226                 "clflush %%fs:-64(%%edx)\n\t"
227
228                  :: "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
229                     "d" (addr_lo +128+16*64), "a"(addr_lo+128),
230                     "D"(addr_lo+128+4*64)
231         );
232 }
233
234
235 static void ReadL18TestPattern(u32 addr_lo)
236 {
237         // set fs and use fs prefix to access the mem
238         __asm__ volatile (
239                 "outb %%al, $0xed\n\t"                  /* _EXECFENCE */
240                 "movl %%fs:-128(%%esi), %%eax\n\t"      //TestAddr cache line
241                 "movl %%fs:-64(%%esi), %%eax\n\t"       //+1
242                 "movl %%fs:(%%esi), %%eax\n\t"          //+2
243                 "movl %%fs:64(%%esi), %%eax\n\t"        //+3
244
245                 "movl %%fs:-128(%%edi), %%eax\n\t"      //+4
246                 "movl %%fs:-64(%%edi), %%eax\n\t"       //+5
247                 "movl %%fs:(%%edi), %%eax\n\t"          //+6
248                 "movl %%fs:64(%%edi), %%eax\n\t"        //+7
249
250                 "movl %%fs:-128(%%ebx), %%eax\n\t"      //+8
251                 "movl %%fs:-64(%%ebx), %%eax\n\t"       //+9
252                 "movl %%fs:(%%ebx), %%eax\n\t"          //+10
253                 "movl %%fs:64(%%ebx), %%eax\n\t"        //+11
254
255                 "movl %%fs:-128(%%ecx), %%eax\n\t"      //+12
256                 "movl %%fs:-64(%%ecx), %%eax\n\t"       //+13
257                 "movl %%fs:(%%ecx), %%eax\n\t"          //+14
258                 "movl %%fs:64(%%ecx), %%eax\n\t"        //+15
259
260                 "movl %%fs:-128(%%edx), %%eax\n\t"      //+16
261                 "movl %%fs:-64(%%edx), %%eax\n\t"       //+17
262                 "mfence\n\t"
263
264                  :: "a"(0), "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
265                     "d" (addr_lo +128+16*64), "S"(addr_lo+128),
266                     "D"(addr_lo+128+4*64)
267         );
268
269 }
270
271
272 static void ReadL9TestPattern(u32 addr_lo)
273 {
274
275         // set fs and use fs prefix to access the mem
276         __asm__ volatile (
277                 "outb %%al, $0xed\n\t"                  /* _EXECFENCE */
278
279                 "movl %%fs:-128(%%ecx), %%eax\n\t"      //TestAddr cache line
280                 "movl %%fs:-64(%%ecx), %%eax\n\t"       //+1
281                 "movl %%fs:(%%ecx), %%eax\n\t"          //+2
282                 "movl %%fs:64(%%ecx), %%eax\n\t"        //+3
283
284                 "movl %%fs:-128(%%edx), %%eax\n\t"      //+4
285                 "movl %%fs:-64(%%edx), %%eax\n\t"       //+5
286                 "movl %%fs:(%%edx), %%eax\n\t"          //+6
287                 "movl %%fs:64(%%edx), %%eax\n\t"        //+7
288
289                 "movl %%fs:-128(%%ebx), %%eax\n\t"      //+8
290                 "mfence\n\t"
291
292                  :: "a"(0), "b" (addr_lo+128+8*64), "c"(addr_lo+128),
293                     "d"(addr_lo+128+4*64)
294         );
295
296 }
297
298
299 static void ReadMaxRdLat1CLTestPattern_D(u32 addr)
300 {
301         SetUpperFSbase(addr);
302
303         __asm__ volatile (
304                 "outb %%al, $0xed\n\t"                  /* _EXECFENCE */
305                 "movl %%fs:-128(%%esi), %%eax\n\t"      //TestAddr cache line
306                 "movl %%fs:-64(%%esi), %%eax\n\t"       //+1
307                 "movl %%fs:(%%esi), %%eax\n\t"          //+2
308                 "mfence\n\t"
309                  :: "a"(0), "S"((addr<<8)+128)
310         );
311
312 }
313
314
315 void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr)
316 {
317         SetUpperFSbase(addr);
318
319         __asm__ volatile (
320                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
321                 "1:\n\t"
322                 "movdqa (%3), %%xmm0\n\t"
323                 "movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
324                 "addl %1, %0\n\t"
325                 "addl %1, %3\n\t"
326                 "loop 1b\n\t"
327                 "mfence\n\t"
328
329                  :: "a" (addr<<8), "d" (16), "c" (3 * 4), "b"(buf)
330         );
331 }
332
333
334 static void FlushMaxRdLatTestPattern_D(u32 addr)
335 {
336         /*  Flush a pattern of 72 bit times (per DQ) from cache.
337          * This procedure is used to ensure cache miss on the next read training.
338          */
339
340         SetUpperFSbase(addr);
341
342         __asm__ volatile (
343                 "outb %%al, $0xed\n\t"  /* _EXECFENCE */
344                 "clflush %%fs:-128(%%esi)\n\t"   //TestAddr cache line
345                 "clflush %%fs:-64(%%esi)\n\t"    //+1
346                 "clflush %%fs:(%%esi)\n\t"  //+2
347                 "mfence\n\t"
348
349                  :: "S"((addr<<8)+128)
350         );
351 }
352
353
354 u32 stream_to_int(u8 *p)
355 {
356         int i;
357         u32 val;
358         u32 valx;
359
360         val = 0;
361
362         for(i=3; i>=0; i--) {
363                 val <<= 8;
364                 valx = *(p+i);
365                 val |= valx;
366         }
367
368         return val;
369 }
370
371
372 void oemSet_NB32(u32 addr, u32 val, u8 *valid)
373 {
374 }
375
376
377 u32 oemGet_NB32(u32 addr,  u8 *valid)
378 {
379         *valid = 0;
380         return 0xffffffff;
381 }
382
383
384 u8 oemNodePresent_D(u8 Node, u8 *ret)
385 {
386         *ret = 0;
387         return 0;
388 }