centaur.c 5.3 KB

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