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