hwmon-vid.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. hwmon-vid.c - VID/VRM/VRD voltage conversions
  3. Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
  4. Partly imported from i2c-vid.h of the lm_sensors project
  5. Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
  6. With assistance from Trent Piepho <xyzzy@speakeasy.org>
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <linux/config.h>
  20. #include <linux/module.h>
  21. #include <linux/kernel.h>
  22. #include <linux/hwmon-vid.h>
  23. /*
  24. Common code for decoding VID pins.
  25. References:
  26. For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
  27. available at http://developer.intel.com/.
  28. For VRD 10.0 and up, "VRD x.y Design Guide",
  29. available at http://developer.intel.com/.
  30. AMD Opteron processors don't follow the Intel specifications.
  31. I'm going to "make up" 2.4 as the spec number for the Opterons.
  32. No good reason just a mnemonic for the 24x Opteron processor
  33. series.
  34. Opteron VID encoding is:
  35. 00000 = 1.550 V
  36. 00001 = 1.525 V
  37. . . . .
  38. 11110 = 0.800 V
  39. 11111 = 0.000 V (off)
  40. */
  41. /* vrm is the VRM/VRD document version multiplied by 10.
  42. val is the 4-, 5- or 6-bit VID code.
  43. Returned value is in mV to avoid floating point in the kernel. */
  44. int vid_from_reg(int val, int vrm)
  45. {
  46. int vid;
  47. switch(vrm) {
  48. case 0:
  49. return 0;
  50. case 100: /* VRD 10.0 */
  51. if((val & 0x1f) == 0x1f)
  52. return 0;
  53. if((val & 0x1f) <= 0x09 || val == 0x0a)
  54. vid = 10875 - (val & 0x1f) * 250;
  55. else
  56. vid = 18625 - (val & 0x1f) * 250;
  57. if(val & 0x20)
  58. vid -= 125;
  59. vid /= 10; /* only return 3 dec. places for now */
  60. return vid;
  61. case 24: /* Opteron processor */
  62. return(val == 0x1f ? 0 : 1550 - val * 25);
  63. case 91: /* VRM 9.1 */
  64. case 90: /* VRM 9.0 */
  65. return(val == 0x1f ? 0 :
  66. 1850 - val * 25);
  67. case 85: /* VRM 8.5 */
  68. return((val & 0x10 ? 25 : 0) +
  69. ((val & 0x0f) > 0x04 ? 2050 : 1250) -
  70. ((val & 0x0f) * 50));
  71. case 84: /* VRM 8.4 */
  72. val &= 0x0f;
  73. /* fall through */
  74. default: /* VRM 8.2 */
  75. return(val == 0x1f ? 0 :
  76. val & 0x10 ? 5100 - (val) * 100 :
  77. 2050 - (val) * 50);
  78. }
  79. }
  80. /*
  81. After this point is the code to automatically determine which
  82. VRM/VRD specification should be used depending on the CPU.
  83. */
  84. struct vrm_model {
  85. u8 vendor;
  86. u8 eff_family;
  87. u8 eff_model;
  88. int vrm_type;
  89. };
  90. #define ANY 0xFF
  91. #ifdef CONFIG_X86
  92. static struct vrm_model vrm_models[] = {
  93. {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
  94. {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
  95. {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
  96. {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* Tualatin */
  97. {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
  98. {X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
  99. {X86_VENDOR_INTEL, 0xF, 0x0, 90}, /* P4 */
  100. {X86_VENDOR_INTEL, 0xF, 0x1, 90}, /* P4 Willamette */
  101. {X86_VENDOR_INTEL, 0xF, 0x2, 90}, /* P4 Northwood */
  102. {X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
  103. {X86_VENDOR_INTEL, 0xF, 0x4, 100}, /* P4 Prescott */
  104. {X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
  105. {X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
  106. };
  107. static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
  108. {
  109. int i = 0;
  110. while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
  111. if (vrm_models[i].vendor==vendor)
  112. if ((vrm_models[i].eff_family==eff_family)
  113. && ((vrm_models[i].eff_model==eff_model) ||
  114. (vrm_models[i].eff_model==ANY)))
  115. return vrm_models[i].vrm_type;
  116. i++;
  117. }
  118. return 0;
  119. }
  120. int vid_which_vrm(void)
  121. {
  122. struct cpuinfo_x86 *c = cpu_data;
  123. u32 eax;
  124. u8 eff_family, eff_model;
  125. int vrm_ret;
  126. if (c->x86 < 6) /* Any CPU with family lower than 6 */
  127. return 0; /* doesn't have VID and/or CPUID */
  128. eax = cpuid_eax(1);
  129. eff_family = ((eax & 0x00000F00)>>8);
  130. eff_model = ((eax & 0x000000F0)>>4);
  131. if (eff_family == 0xF) { /* use extended model & family */
  132. eff_family += ((eax & 0x00F00000)>>20);
  133. eff_model += ((eax & 0x000F0000)>>16)<<4;
  134. }
  135. vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
  136. if (vrm_ret == 0)
  137. printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
  138. "x86 CPU\n");
  139. return vrm_ret;
  140. }
  141. /* and now something completely different for the non-x86 world */
  142. #else
  143. int vid_which_vrm(void)
  144. {
  145. printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
  146. return 0;
  147. }
  148. #endif
  149. EXPORT_SYMBOL(vid_from_reg);
  150. EXPORT_SYMBOL(vid_which_vrm);
  151. MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
  152. MODULE_DESCRIPTION("hwmon-vid driver");
  153. MODULE_LICENSE("GPL");