- Moved hlt() to it's own header.
[coreboot.git] / src / cpu / k8 / cpufixup.c
1 /* Needed so the AMD K8 runs correctly.  */
2 #include <console/console.h>
3 #include <mem.h>
4 #include <cpu/p6/msr.h>
5 #include <cpu/k8/mtrr.h>
6 #include <device/device.h>
7 #include <device/chip.h>
8 #include <device/device.h>
9 #include <device/pci.h>
10 #include <smp/start_stop.h>
11 #include <string.h>
12 #include <cpu/p6/msr.h>
13 #include <cpu/p6/pgtbl.h>
14 #include <pc80/mc146818rtc.h>
15 #include <arch/smp/lapic.h>
16 #include "../../northbridge/amd/amdk8/amdk8.h"
17 #include "../../northbridge/amd/amdk8/cpu_rev.c"
18 #include "chip.h"
19
20 #define MCI_STATUS 0x401
21
22 static inline void disable_cache(void)
23 {
24         unsigned int tmp;
25         /* Disable cache */
26         /* Write back the cache */
27         asm volatile (
28                 "movl  %%cr0, %0\n\t"
29                 "orl  $0x40000000, %0\n\t"
30                 "wbinvd\n\t"
31                 "movl  %0, %%cr0\n\t"
32                 "wbinvd\n\t"
33                 :"=r" (tmp)
34                 ::"memory");
35 }
36
37 static inline void enable_cache(void)
38 {
39         unsigned int tmp;
40         // turn cache back on. 
41         asm volatile (
42                 "movl  %%cr0, %0\n\t"
43                 "andl  $0x9fffffff, %0\n\t"
44                 "movl  %0, %%cr0\n\t"
45                 :"=r" (tmp)
46                 ::"memory");
47 }
48
49 static inline msr_t rdmsr_amd(unsigned index)
50 {
51         msr_t result;
52         __asm__ __volatile__ (
53                 "rdmsr"
54                 : "=a" (result.lo), "=d" (result.hi)
55                 : "c" (index), "D" (0x9c5a203a)
56                 );
57         return result;
58 }
59
60 static inline void wrmsr_amd(unsigned index, msr_t msr)
61 {
62         __asm__ __volatile__ (
63                 "wrmsr"
64                 : /* No outputs */
65                 : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a)
66                 );
67 }
68
69
70
71 #define MTRR_COUNT 8
72 #define ZERO_CHUNK_KB 0x800UL /* 2M */
73 #define TOLM_KB 0x400000UL
74
75 struct mtrr {
76         msr_t base;
77         msr_t mask;
78 };
79 struct mtrr_state {
80         struct mtrr mtrrs[MTRR_COUNT];
81         msr_t top_mem, top_mem2;
82         msr_t def_type;
83 };
84
85 static void save_mtrr_state(struct mtrr_state *state)
86 {
87         int i;
88         for(i = 0; i < MTRR_COUNT; i++) {
89                 state->mtrrs[i].base = rdmsr(MTRRphysBase_MSR(i));
90                 state->mtrrs[i].mask = rdmsr(MTRRphysMask_MSR(i));
91         }
92         state->top_mem  = rdmsr(TOP_MEM);
93         state->top_mem2 = rdmsr(TOP_MEM2);
94         state->def_type = rdmsr(MTRRdefType_MSR);
95 }
96
97 static void restore_mtrr_state(struct mtrr_state *state)
98 {
99         int i;
100         disable_cache();
101
102         for(i = 0; i < MTRR_COUNT; i++) {
103                 wrmsr(MTRRphysBase_MSR(i), state->mtrrs[i].base);
104                 wrmsr(MTRRphysMask_MSR(i), state->mtrrs[i].mask);
105         }
106         wrmsr(TOP_MEM,         state->top_mem);
107         wrmsr(TOP_MEM2,        state->top_mem2);
108         wrmsr(MTRRdefType_MSR, state->def_type);
109
110         enable_cache();
111 }
112
113
114 #if 0
115 static void print_mtrr_state(struct mtrr_state *state)
116 {
117         int i;
118         for(i = 0; i < MTRR_COUNT; i++) {
119                 printk_debug("var mtrr %d: %08x%08x mask: %08x%08x\n",
120                         i,
121                         state->mtrrs[i].base.hi, state->mtrrs[i].base.lo,
122                         state->mtrrs[i].mask.hi, state->mtrrs[i].mask.lo);
123         }
124         printk_debug("top_mem:  %08x%08x\n",
125                 state->top_mem.hi, state->top_mem.lo);
126         printk_debug("top_mem2: %08x%08x\n",
127                 state->top_mem2.hi, state->top_mem2.lo);
128         printk_debug("def_type: %08x%08x\n",
129                 state->def_type.hi, state->def_type.lo);
130 }
131 #endif
132
133 static void set_init_ecc_mtrrs(void)
134 {
135         msr_t msr;
136         int i;
137         disable_cache();
138
139         /* First clear all of the msrs to be safe */
140         for(i = 0; i < MTRR_COUNT; i++) {
141                 msr_t zero;
142                 zero.lo = zero.hi = 0;
143                 wrmsr(MTRRphysBase_MSR(i), zero);
144                 wrmsr(MTRRphysMask_MSR(i), zero);
145         }
146
147         /* Write back cache the first 1MB */
148         msr.hi = 0x00000000;
149         msr.lo = 0x00000000 | MTRR_TYPE_WRBACK;
150         wrmsr(MTRRphysBase_MSR(0), msr);
151         msr.hi = 0x000000ff;
152         msr.lo = ~((CONFIG_LB_MEM_TOPK << 10) - 1) | 0x800;
153         wrmsr(MTRRphysMask_MSR(0), msr);
154
155         /* Set the default type to write combining */
156         msr.hi = 0x00000000;
157         msr.lo = 0xc00 | MTRR_TYPE_WRCOMB;
158         wrmsr(MTRRdefType_MSR, msr);
159
160         /* Set TOP_MEM to 4G */
161         msr.hi = 0x00000001;
162         msr.lo = 0x00000000;
163         wrmsr(TOP_MEM, msr);
164
165         enable_cache();
166 }
167
168
169 static void init_ecc_memory(void)
170 {
171         unsigned long startk, begink, endk;
172         unsigned long basek;
173         struct mtrr_state mtrr_state;
174         device_t f1_dev, f2_dev, f3_dev;
175         int cpu_index, cpu_id, node_id;
176         int enable_scrubbing;
177         uint32_t dcl;
178         cpu_id = this_processors_id();
179         cpu_index = processor_index(cpu_id);
180         /* For now there is a 1-1 mapping between node_id and cpu_id */
181         node_id = cpu_id;
182
183         f1_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 1));
184         if (!f1_dev) {
185                 die("Cannot find cpu function 1\n");
186         }
187         f2_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 2));
188         if (!f2_dev) {
189                 die("Cannot find cpu function 2\n");
190         }
191         f3_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 3));
192         if (!f3_dev) {
193                 die("Cannot find cpu function 3\n");
194         }
195
196         /* See if we scrubbing should be enabled */
197         enable_scrubbing = 1;
198         get_option(&enable_scrubbing, "hw_scrubber");
199
200         /* Enable cache scrubbing at the lowest possible rate */
201         if (enable_scrubbing) {
202                 pci_write_config32(f3_dev, SCRUB_CONTROL,
203                         (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_NONE << 0));
204         } else {
205                 pci_write_config32(f3_dev, SCRUB_CONTROL,
206                         (SCRUB_NONE << 16) | (SCRUB_NONE << 8) | (SCRUB_NONE << 0));
207                 printk_debug("Scrubbing Disabled\n");
208         }
209         
210
211         /* If ecc support is not enabled don't touch memory */
212         dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
213         if (!(dcl & DCL_DimmEccEn)) {
214                 return;
215         }
216
217         startk = (pci_read_config32(f1_dev, 0x40 + (node_id*8)) & 0xffff0000) >> 2;
218         endk   = ((pci_read_config32(f1_dev, 0x44 + (node_id*8)) & 0xffff0000) >> 2) + 0x4000;
219
220         /* Don't start too early */
221         begink = startk;
222         if (begink < CONFIG_LB_MEM_TOPK) {
223                 begink = CONFIG_LB_MEM_TOPK;
224         }
225         printk_debug("Clearing memory %uK - %uK: ", startk, endk);
226
227         /* Save the normal state */
228         save_mtrr_state(&mtrr_state);
229
230         /* Switch to the init ecc state */
231         set_init_ecc_mtrrs();
232         disable_lapic();
233
234         /* Walk through 2M chunks and zero them */
235         for(basek = begink; basek < endk; basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1))) {
236                 unsigned long limitk;
237                 unsigned long size;
238                 void *addr;
239
240                 /* Report every 64M */
241                 if ((basek % (64*1024)) == 0) {
242                         /* Restore the normal state */
243                         map_2M_page(cpu_index, 0);
244                         restore_mtrr_state(&mtrr_state);
245                         enable_lapic();
246
247                         /* Print a status message */
248                         printk_debug("%c", (basek >= TOLM_KB)?'+':'-');
249
250                         /* Return to the initialization state */
251                         set_init_ecc_mtrrs();
252                         disable_lapic();
253                 }
254                 limitk = (basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1);
255                 if (limitk > endk) {
256                         limitk = endk;
257                 }
258                 size = (limitk - basek) << 10;
259                 addr = map_2M_page(cpu_index, basek >> 11);
260                 addr = (void *)(((uint32_t)addr) | ((basek & 0x7ff) << 10));
261                 if (addr == MAPPING_ERROR) {
262                         continue;
263                 }
264
265                 /* clear memory 2M (limitk - basek) */
266                 __asm__ volatile(
267                         "1: \n\t"
268                         "movl %0, (%1)\n\t"
269                         "addl $4,%1\n\t"
270                         "subl $4,%2\n\t"
271                         "jnz 1b\n\t"
272                         :
273                         : "a" (0), "D" (addr),  "c" (size)
274                         );
275         }
276         /* Restore the normal state */
277         map_2M_page(cpu_index, 0);
278         restore_mtrr_state(&mtrr_state);
279         enable_lapic();
280
281         /* Set the scrub base address registers */
282         pci_write_config32(f3_dev, SCRUB_ADDR_LOW,  startk << 10);
283         pci_write_config32(f3_dev, SCRUB_ADDR_HIGH, startk >> 22);
284
285         /* Enable the scrubber? */
286         if (enable_scrubbing) {
287                 /* Enable scrubbing at the lowest possible rate */
288                 pci_write_config32(f3_dev, SCRUB_CONTROL,
289                         (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_84ms << 0));
290         }
291
292         printk_debug(" done\n");
293 }
294
295 void k8_cpufixup(struct mem_range *mem)
296 {
297         unsigned long mmio_basek, tomk;
298         unsigned long i;
299         msr_t msr;
300
301         disable_cache();
302         
303         /* Except for the PCI MMIO hold just before 4GB there are no
304          * significant holes in the address space, so just account
305          * for those two and move on.
306          */
307         mmio_basek = tomk = 0;
308         for(i = 0; mem[i].sizek; i++) {
309                 unsigned long topk;
310                 topk = mem[i].basek + mem[i].sizek;
311                 if (tomk < topk) {
312                         tomk = topk;
313                 }
314                 if ((topk < 4*1024*1024) && (mmio_basek < topk)) {
315                         mmio_basek = topk;
316                 }
317         }
318         if (mmio_basek > tomk) {
319                 mmio_basek = tomk;
320         }
321         /* Round mmio_basek down to the nearst size that will fit in TOP_MEM */
322         mmio_basek = mmio_basek & ~TOP_MEM_MASK_KB;
323         /* Round tomk up to the next greater size that will fit in TOP_MEM */
324         tomk = (tomk + TOP_MEM_MASK_KB) & ~TOP_MEM_MASK_KB;
325                 
326         /* Setup TOP_MEM */
327         msr.hi = mmio_basek >> 22;
328         msr.lo = mmio_basek << 10;
329         wrmsr(TOP_MEM, msr);
330
331         /* Setup TOP_MEM2 */
332         msr.hi = tomk >> 22;
333         msr.lo = tomk << 10;
334         wrmsr(TOP_MEM2, msr);
335
336         /* zero the IORR's before we enable to prevent
337          * undefined side effects.
338          */
339         msr.lo = msr.hi = 0;
340         for(i = IORR_FIRST; i <= IORR_LAST; i++) {
341                 wrmsr(i, msr);
342         }
343
344         msr = rdmsr(SYSCFG_MSR);
345         msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En;
346         wrmsr(SYSCFG_MSR, msr);
347
348         /* zero the machine check error status registers */
349         msr.lo = 0;
350         msr.hi = 0;
351         for(i=0; i<5; i++) {
352                 wrmsr(MCI_STATUS + (i*4),msr);
353         }
354         
355         if (is_cpu_pre_c0()) {
356                 /* Erratum 63... */
357                 msr = rdmsr(HWCR_MSR);
358                 msr.lo |= (1 << 6);
359                 wrmsr(HWCR_MSR, msr);
360
361                 /* Erratum 69... */
362                 msr = rdmsr_amd(BU_CFG_MSR);
363                 msr.hi |= (1 << (45 - 32));
364                 wrmsr_amd(BU_CFG_MSR, msr);
365
366                 /* Erratum 81... */
367                 msr = rdmsr_amd(DC_CFG_MSR);
368                 msr.lo |=  (1 << 10);
369                 wrmsr_amd(DC_CFG_MSR, msr);
370                         
371         }
372         /* I can't touch this msr on early buggy cpus */
373         if (!is_cpu_pre_b3()) {
374
375                 /* Erratum 89 ... */
376                 msr = rdmsr(NB_CFG_MSR);
377                 msr.lo |= 1 << 3;
378                 
379                 if (!is_cpu_pre_c0()) {
380                         /* Erratum 86 Disable data masking on C0 and 
381                          * later processor revs.
382                          * FIXME this is only needed if ECC is enabled.
383                          */
384                         msr.hi |= 1 << (36 - 32);
385                 }       
386                 wrmsr(NB_CFG_MSR, msr);
387         }
388         
389         /* Erratum 97 ... */
390         if (!is_cpu_pre_c0()) {
391                 msr = rdmsr_amd(DC_CFG_MSR);
392                 msr.lo |= 1 << 3;
393                 wrmsr_amd(DC_CFG_MSR, msr);
394         }       
395         
396         /* Erratum 94 ... */
397         msr = rdmsr_amd(IC_CFG_MSR);
398         msr.lo |= 1 << 11;
399         wrmsr_amd(IC_CFG_MSR, msr);
400
401         /* Erratum 91 prefetch miss is handled in the kernel */
402         
403         enable_cache();
404
405         /* Is this a bad location?  In particular can another node prefecth
406          * data from this node before we have initialized it?
407          */
408         init_ecc_memory();
409 }
410
411 static
412 void k8_enable(struct chip *chip, enum chip_pass pass)
413 {
414
415         struct cpu_k8_config *conf = (struct cpu_k8_config *)chip->chip_info;
416
417         switch (pass) {
418         case CONF_PASS_PRE_CONSOLE:
419                 break;
420         case CONF_PASS_PRE_PCI:
421                 init_timer();
422                 break;
423         default:
424                 /* nothing yet */
425                 break;
426         }
427 }
428
429 struct chip_control cpu_k8_control = {
430         .enable = k8_enable,
431         .name   = "AMD K8",
432 };