Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #include <linux/init.h> |
2 | #include <linux/mm.h> | |
6c4caa1a | 3 | |
1da177e4 LT |
4 | #include <asm/mtrr.h> |
5 | #include <asm/msr.h> | |
6c4caa1a | 6 | |
1da177e4 LT |
7 | #include "mtrr.h" |
8 | ||
9 | static struct { | |
10 | unsigned long high; | |
11 | unsigned long low; | |
12 | } centaur_mcr[8]; | |
13 | ||
14 | static u8 centaur_mcr_reserved; | |
15 | static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */ | |
16 | ||
6c4caa1a JSR |
17 | /** |
18 | * centaur_get_free_region - Get a free MTRR. | |
19 | * | |
20 | * @base: The starting (base) address of the region. | |
21 | * @size: The size (in bytes) of the region. | |
22 | * | |
23 | * Returns: the index of the region on success, else -1 on error. | |
1da177e4 | 24 | */ |
1da177e4 | 25 | static int |
365bff80 | 26 | centaur_get_free_region(unsigned long base, unsigned long size, int replace_reg) |
1da177e4 | 27 | { |
365bff80 | 28 | unsigned long lbase, lsize; |
6c4caa1a JSR |
29 | mtrr_type ltype; |
30 | int i, max; | |
1da177e4 LT |
31 | |
32 | max = num_var_ranges; | |
365bff80 JB |
33 | if (replace_reg >= 0 && replace_reg < max) |
34 | return replace_reg; | |
6c4caa1a | 35 | |
1da177e4 LT |
36 | for (i = 0; i < max; ++i) { |
37 | if (centaur_mcr_reserved & (1 << i)) | |
38 | continue; | |
39 | mtrr_if->get(i, &lbase, &lsize, <ype); | |
40 | if (lsize == 0) | |
41 | return i; | |
42 | } | |
6c4caa1a | 43 | |
1da177e4 LT |
44 | return -ENOSPC; |
45 | } | |
46 | ||
6c4caa1a JSR |
47 | /* |
48 | * Report boot time MCR setups | |
49 | */ | |
50 | void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) | |
1da177e4 LT |
51 | { |
52 | centaur_mcr[mcr].low = lo; | |
53 | centaur_mcr[mcr].high = hi; | |
54 | } | |
55 | ||
56 | static void | |
57 | centaur_get_mcr(unsigned int reg, unsigned long *base, | |
365bff80 | 58 | unsigned long *size, mtrr_type * type) |
1da177e4 LT |
59 | { |
60 | *base = centaur_mcr[reg].high >> PAGE_SHIFT; | |
61 | *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT; | |
6c4caa1a JSR |
62 | *type = MTRR_TYPE_WRCOMB; /* write-combining */ |
63 | ||
1da177e4 LT |
64 | if (centaur_mcr_type == 1 && ((centaur_mcr[reg].low & 31) & 2)) |
65 | *type = MTRR_TYPE_UNCACHABLE; | |
66 | if (centaur_mcr_type == 1 && (centaur_mcr[reg].low & 31) == 25) | |
67 | *type = MTRR_TYPE_WRBACK; | |
68 | if (centaur_mcr_type == 0 && (centaur_mcr[reg].low & 31) == 31) | |
69 | *type = MTRR_TYPE_WRBACK; | |
1da177e4 LT |
70 | } |
71 | ||
6c4caa1a JSR |
72 | static void |
73 | centaur_set_mcr(unsigned int reg, unsigned long base, | |
74 | unsigned long size, mtrr_type type) | |
1da177e4 LT |
75 | { |
76 | unsigned long low, high; | |
77 | ||
78 | if (size == 0) { | |
6c4caa1a | 79 | /* Disable */ |
1da177e4 LT |
80 | high = low = 0; |
81 | } else { | |
82 | high = base << PAGE_SHIFT; | |
6c4caa1a JSR |
83 | if (centaur_mcr_type == 0) { |
84 | /* Only support write-combining... */ | |
85 | low = -size << PAGE_SHIFT | 0x1f; | |
86 | } else { | |
1da177e4 | 87 | if (type == MTRR_TYPE_UNCACHABLE) |
6c4caa1a | 88 | low = -size << PAGE_SHIFT | 0x02; /* NC */ |
1da177e4 | 89 | else |
6c4caa1a | 90 | low = -size << PAGE_SHIFT | 0x09; /* WWO, WC */ |
1da177e4 LT |
91 | } |
92 | } | |
93 | centaur_mcr[reg].high = high; | |
94 | centaur_mcr[reg].low = low; | |
95 | wrmsr(MSR_IDT_MCR0 + reg, low, high); | |
96 | } | |
97 | ||
6c4caa1a JSR |
98 | static int |
99 | centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int type) | |
1da177e4 LT |
100 | { |
101 | /* | |
6c4caa1a | 102 | * FIXME: Winchip2 supports uncached |
1da177e4 | 103 | */ |
6c4caa1a | 104 | if (type != MTRR_TYPE_WRCOMB && |
1da177e4 | 105 | (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE)) { |
6c4caa1a JSR |
106 | pr_warning("mtrr: only write-combining%s supported\n", |
107 | centaur_mcr_type ? " and uncacheable are" : " is"); | |
1da177e4 LT |
108 | return -EINVAL; |
109 | } | |
110 | return 0; | |
111 | } | |
112 | ||
113 | static struct mtrr_ops centaur_mtrr_ops = { | |
114 | .vendor = X86_VENDOR_CENTAUR, | |
1da177e4 LT |
115 | .set = centaur_set_mcr, |
116 | .get = centaur_get_mcr, | |
117 | .get_free_region = centaur_get_free_region, | |
118 | .validate_add_page = centaur_validate_add_page, | |
119 | .have_wrcomb = positive_have_wrcomb, | |
120 | }; | |
121 | ||
122 | int __init centaur_init_mtrr(void) | |
123 | { | |
124 | set_mtrr_ops(¢aur_mtrr_ops); | |
125 | return 0; | |
126 | } |