diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 05:16:28 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 05:16:28 -0400 |
commit | 2ec1df4130c60d1eb49dc0fa0ed15858fede6b05 (patch) | |
tree | 97e578ba1546770eadbe84cff2dc44256f97b9d7 /arch/x86/kernel/cpu/mtrr/centaur.c | |
parent | ee580dc91efd83e6b55955e7261e8ad2a0e08d1a (diff) |
i386: move kernel/cpu/mtrr
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/cpu/mtrr/centaur.c')
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/centaur.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c new file mode 100644 index 000000000000..cb9aa3a7a7ab --- /dev/null +++ b/arch/x86/kernel/cpu/mtrr/centaur.c | |||
@@ -0,0 +1,224 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/mm.h> | ||
3 | #include <asm/mtrr.h> | ||
4 | #include <asm/msr.h> | ||
5 | #include "mtrr.h" | ||
6 | |||
7 | static struct { | ||
8 | unsigned long high; | ||
9 | unsigned long low; | ||
10 | } centaur_mcr[8]; | ||
11 | |||
12 | static u8 centaur_mcr_reserved; | ||
13 | static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */ | ||
14 | |||
15 | /* | ||
16 | * Report boot time MCR setups | ||
17 | */ | ||
18 | |||
19 | static int | ||
20 | centaur_get_free_region(unsigned long base, unsigned long size, int replace_reg) | ||
21 | /* [SUMMARY] Get a free MTRR. | ||
22 | <base> The starting (base) address of the region. | ||
23 | <size> The size (in bytes) of the region. | ||
24 | [RETURNS] The index of the region on success, else -1 on error. | ||
25 | */ | ||
26 | { | ||
27 | int i, max; | ||
28 | mtrr_type ltype; | ||
29 | unsigned long lbase, lsize; | ||
30 | |||
31 | max = num_var_ranges; | ||
32 | if (replace_reg >= 0 && replace_reg < max) | ||
33 | return replace_reg; | ||
34 | for (i = 0; i < max; ++i) { | ||
35 | if (centaur_mcr_reserved & (1 << i)) | ||
36 | continue; | ||
37 | mtrr_if->get(i, &lbase, &lsize, <ype); | ||
38 | if (lsize == 0) | ||
39 | return i; | ||
40 | } | ||
41 | return -ENOSPC; | ||
42 | } | ||
43 | |||
44 | void | ||
45 | mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) | ||
46 | { | ||
47 | centaur_mcr[mcr].low = lo; | ||
48 | centaur_mcr[mcr].high = hi; | ||
49 | } | ||
50 | |||
51 | static void | ||
52 | centaur_get_mcr(unsigned int reg, unsigned long *base, | ||
53 | unsigned long *size, mtrr_type * type) | ||
54 | { | ||
55 | *base = centaur_mcr[reg].high >> PAGE_SHIFT; | ||
56 | *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT; | ||
57 | *type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */ | ||
58 | if (centaur_mcr_type == 1 && ((centaur_mcr[reg].low & 31) & 2)) | ||
59 | *type = MTRR_TYPE_UNCACHABLE; | ||
60 | if (centaur_mcr_type == 1 && (centaur_mcr[reg].low & 31) == 25) | ||
61 | *type = MTRR_TYPE_WRBACK; | ||
62 | if (centaur_mcr_type == 0 && (centaur_mcr[reg].low & 31) == 31) | ||
63 | *type = MTRR_TYPE_WRBACK; | ||
64 | |||
65 | } | ||
66 | |||
67 | static void centaur_set_mcr(unsigned int reg, unsigned long base, | ||
68 | unsigned long size, mtrr_type type) | ||
69 | { | ||
70 | unsigned long low, high; | ||
71 | |||
72 | if (size == 0) { | ||
73 | /* Disable */ | ||
74 | high = low = 0; | ||
75 | } else { | ||
76 | high = base << PAGE_SHIFT; | ||
77 | if (centaur_mcr_type == 0) | ||
78 | low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */ | ||
79 | else { | ||
80 | if (type == MTRR_TYPE_UNCACHABLE) | ||
81 | low = -size << PAGE_SHIFT | 0x02; /* NC */ | ||
82 | else | ||
83 | low = -size << PAGE_SHIFT | 0x09; /* WWO,WC */ | ||
84 | } | ||
85 | } | ||
86 | centaur_mcr[reg].high = high; | ||
87 | centaur_mcr[reg].low = low; | ||
88 | wrmsr(MSR_IDT_MCR0 + reg, low, high); | ||
89 | } | ||
90 | |||
91 | #if 0 | ||
92 | /* | ||
93 | * Initialise the later (saner) Winchip MCR variant. In this version | ||
94 | * the BIOS can pass us the registers it has used (but not their values) | ||
95 | * and the control register is read/write | ||
96 | */ | ||
97 | |||
98 | static void __init | ||
99 | centaur_mcr1_init(void) | ||
100 | { | ||
101 | unsigned i; | ||
102 | u32 lo, hi; | ||
103 | |||
104 | /* Unfortunately, MCR's are read-only, so there is no way to | ||
105 | * find out what the bios might have done. | ||
106 | */ | ||
107 | |||
108 | rdmsr(MSR_IDT_MCR_CTRL, lo, hi); | ||
109 | if (((lo >> 17) & 7) == 1) { /* Type 1 Winchip2 MCR */ | ||
110 | lo &= ~0x1C0; /* clear key */ | ||
111 | lo |= 0x040; /* set key to 1 */ | ||
112 | wrmsr(MSR_IDT_MCR_CTRL, lo, hi); /* unlock MCR */ | ||
113 | } | ||
114 | |||
115 | centaur_mcr_type = 1; | ||
116 | |||
117 | /* | ||
118 | * Clear any unconfigured MCR's. | ||
119 | */ | ||
120 | |||
121 | for (i = 0; i < 8; ++i) { | ||
122 | if (centaur_mcr[i].high == 0 && centaur_mcr[i].low == 0) { | ||
123 | if (!(lo & (1 << (9 + i)))) | ||
124 | wrmsr(MSR_IDT_MCR0 + i, 0, 0); | ||
125 | else | ||
126 | /* | ||
127 | * If the BIOS set up an MCR we cannot see it | ||
128 | * but we don't wish to obliterate it | ||
129 | */ | ||
130 | centaur_mcr_reserved |= (1 << i); | ||
131 | } | ||
132 | } | ||
133 | /* | ||
134 | * Throw the main write-combining switch... | ||
135 | * However if OOSTORE is enabled then people have already done far | ||
136 | * cleverer things and we should behave. | ||
137 | */ | ||
138 | |||
139 | lo |= 15; /* Write combine enables */ | ||
140 | wrmsr(MSR_IDT_MCR_CTRL, lo, hi); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Initialise the original winchip with read only MCR registers | ||
145 | * no used bitmask for the BIOS to pass on and write only control | ||
146 | */ | ||
147 | |||
148 | static void __init | ||
149 | centaur_mcr0_init(void) | ||
150 | { | ||
151 | unsigned i; | ||
152 | |||
153 | /* Unfortunately, MCR's are read-only, so there is no way to | ||
154 | * find out what the bios might have done. | ||
155 | */ | ||
156 | |||
157 | /* Clear any unconfigured MCR's. | ||
158 | * This way we are sure that the centaur_mcr array contains the actual | ||
159 | * values. The disadvantage is that any BIOS tweaks are thus undone. | ||
160 | * | ||
161 | */ | ||
162 | for (i = 0; i < 8; ++i) { | ||
163 | if (centaur_mcr[i].high == 0 && centaur_mcr[i].low == 0) | ||
164 | wrmsr(MSR_IDT_MCR0 + i, 0, 0); | ||
165 | } | ||
166 | |||
167 | wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0); /* Write only */ | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Initialise Winchip series MCR registers | ||
172 | */ | ||
173 | |||
174 | static void __init | ||
175 | centaur_mcr_init(void) | ||
176 | { | ||
177 | struct set_mtrr_context ctxt; | ||
178 | |||
179 | set_mtrr_prepare_save(&ctxt); | ||
180 | set_mtrr_cache_disable(&ctxt); | ||
181 | |||
182 | if (boot_cpu_data.x86_model == 4) | ||
183 | centaur_mcr0_init(); | ||
184 | else if (boot_cpu_data.x86_model == 8 || boot_cpu_data.x86_model == 9) | ||
185 | centaur_mcr1_init(); | ||
186 | |||
187 | set_mtrr_done(&ctxt); | ||
188 | } | ||
189 | #endif | ||
190 | |||
191 | static int centaur_validate_add_page(unsigned long base, | ||
192 | unsigned long size, unsigned int type) | ||
193 | { | ||
194 | /* | ||
195 | * FIXME: Winchip2 supports uncached | ||
196 | */ | ||
197 | if (type != MTRR_TYPE_WRCOMB && | ||
198 | (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE)) { | ||
199 | printk(KERN_WARNING | ||
200 | "mtrr: only write-combining%s supported\n", | ||
201 | centaur_mcr_type ? " and uncacheable are" | ||
202 | : " is"); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static struct mtrr_ops centaur_mtrr_ops = { | ||
209 | .vendor = X86_VENDOR_CENTAUR, | ||
210 | // .init = centaur_mcr_init, | ||
211 | .set = centaur_set_mcr, | ||
212 | .get = centaur_get_mcr, | ||
213 | .get_free_region = centaur_get_free_region, | ||
214 | .validate_add_page = centaur_validate_add_page, | ||
215 | .have_wrcomb = positive_have_wrcomb, | ||
216 | }; | ||
217 | |||
218 | int __init centaur_init_mtrr(void) | ||
219 | { | ||
220 | set_mtrr_ops(¢aur_mtrr_ops); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | //arch_initcall(centaur_init_mtrr); | ||