ab6bc2bbee830e8e66b293d817bbbdf40cde299d
[coreboot.git] / src / cpu / amd / mtrr / amd_mtrr.c
1 #include <console/console.h>
2 #include <device/device.h>
3 #include <cpu/x86/mtrr.h>
4 #include <cpu/amd/mtrr.h>
5 #include <cpu/x86/cache.h>
6 #include <cpu/x86/msr.h>
7
8 static unsigned long resk(uint64_t value) 
9 {
10         unsigned long resultk;
11         if (value < (1ULL << 42)) {
12                 resultk = value >> 10;
13         }
14         else {
15                 resultk = 0xffffffff;
16         }
17         return resultk;
18 }
19
20 void amd_setup_mtrrs(void)
21 {
22         unsigned long mmio_basek, tomk;
23         unsigned long i;
24         device_t dev;
25         msr_t msr;
26
27         /* Disable the access to AMD RdDram and WrDram extension bits */
28         msr = rdmsr(SYSCFG_MSR);
29         msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
30         wrmsr(SYSCFG_MSR, msr);
31
32         x86_setup_mtrrs();
33
34         /* Except for the PCI MMIO hole just before 4GB there are no
35          * significant holes in the address space, so just account
36          * for those two and move on.
37          */
38         mmio_basek = tomk = 0;
39         for(dev = all_devices; dev; dev = dev->next) {
40                 struct resource *res, *last;
41                 last = &dev->resource[dev->resources];
42                 for(res = &dev->resource[0]; res < last; res++) {
43                         unsigned long topk;
44                         if (!(res->flags & IORESOURCE_MEM) ||
45                                 (!(res->flags & IORESOURCE_CACHEABLE))) {
46                                 continue;
47                         }
48                         topk = resk(res->base + res->size);
49                         if (tomk < topk) {
50                                 tomk = topk;
51                         }
52                         if ((topk < 4*1024*1024) && (mmio_basek < topk)) {
53                                 mmio_basek = topk;
54                         }
55                 }
56         }
57         if (mmio_basek > tomk) {
58                 mmio_basek = tomk;
59         }
60         /* Round mmio_basek down to the nearst size that will fit in TOP_MEM */
61         mmio_basek = mmio_basek & ~TOP_MEM_MASK_KB;
62         /* Round tomk up to the next greater size that will fit in TOP_MEM */
63         tomk = (tomk + TOP_MEM_MASK_KB) & ~TOP_MEM_MASK_KB;
64
65         disable_cache();
66
67         /* Setup TOP_MEM */
68         msr.hi = mmio_basek >> 22;
69         msr.lo = mmio_basek << 10;
70         wrmsr(TOP_MEM, msr);
71
72         /* Setup TOP_MEM2 */
73         msr.hi = tomk >> 22;
74         msr.lo = tomk << 10;
75         wrmsr(TOP_MEM2, msr);
76
77         /* zero the IORR's before we enable to prevent
78          * undefined side effects.
79          */
80         msr.lo = msr.hi = 0;
81         for(i = IORR_FIRST; i <= IORR_LAST; i++) {
82                 wrmsr(i, msr);
83         }
84
85         msr = rdmsr(SYSCFG_MSR);
86         msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En;
87         wrmsr(SYSCFG_MSR, msr);
88
89         enable_cache();
90 }