blob: a6764ff00803bb2d43e7e0d2633351ada41c26a6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Jean Delvare303760b2005-07-31 21:52:01 +02002 hwmon-vid.c - VID/VRM/VRD voltage conversions
Linus Torvalds1da177e2005-04-16 15:20:36 -07003
4 Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
5
Jean Delvared0f28272005-08-01 22:50:08 +02006 Partly imported from i2c-vid.h of the lm_sensors project
7 Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
8 With assistance from Trent Piepho <xyzzy@speakeasy.org>
9
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25#include <linux/config.h>
26#include <linux/module.h>
27#include <linux/kernel.h>
Jean Delvare303760b2005-07-31 21:52:01 +020028#include <linux/hwmon-vid.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Jean Delvared0f28272005-08-01 22:50:08 +020030/*
31 Common code for decoding VID pins.
32
33 References:
34
35 For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
36 available at http://developer.intel.com/.
37
38 For VRD 10.0 and up, "VRD x.y Design Guide",
39 available at http://developer.intel.com/.
40
41 AMD Opteron processors don't follow the Intel specifications.
42 I'm going to "make up" 2.4 as the spec number for the Opterons.
43 No good reason just a mnemonic for the 24x Opteron processor
44 series.
45
46 Opteron VID encoding is:
47 00000 = 1.550 V
48 00001 = 1.525 V
49 . . . .
50 11110 = 0.800 V
51 11111 = 0.000 V (off)
Rudolf Marek734a12a2005-12-18 16:36:52 +010052
53 The 17 specification is in fact Intel Mobile Voltage Positioning -
54 (IMVP-II). You can find more information in the datasheet of Max1718
55 http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452
56
Jean Delvare4c537fb2006-02-05 23:21:05 +010057 The 13 specification corresponds to the Intel Pentium M series. There
58 doesn't seem to be any named specification for these. The conversion
59 tables are detailed directly in the various Pentium M datasheets:
60 http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm
Rudolf Marek6af586d2006-06-12 22:00:53 +020061
62 The 14 specification corresponds to Intel Core series. There
63 doesn't seem to be any named specification for these. The conversion
64 tables are detailed directly in the various Pentium Core datasheets:
65 http://www.intel.com/design/mobile/datashts/309221.htm
66
67 The 110 (VRM 11) specification corresponds to Intel Conroe based series.
68 http://www.intel.com/design/processor/applnots/313214.htm
Jean Delvared0f28272005-08-01 22:50:08 +020069*/
70
71/* vrm is the VRM/VRD document version multiplied by 10.
Rudolf Marek6af586d2006-06-12 22:00:53 +020072 val is the 4-bit or more VID code.
73 Returned value is in mV to avoid floating point in the kernel.
74 Some VID have some bits in uV scale, this is rounded to mV */
Rudolf Marek734a12a2005-12-18 16:36:52 +010075int vid_from_reg(int val, u8 vrm)
Jean Delvared0f28272005-08-01 22:50:08 +020076{
77 int vid;
78
79 switch(vrm) {
80
Jean Delvared0f28272005-08-01 22:50:08 +020081 case 100: /* VRD 10.0 */
Rudolf Marek6af586d2006-06-12 22:00:53 +020082 /* compute in uV, round to mV */
Rudolf Marek177d1652006-04-25 14:24:46 +020083 val &= 0x3f;
Jean Delvared0f28272005-08-01 22:50:08 +020084 if((val & 0x1f) == 0x1f)
85 return 0;
86 if((val & 0x1f) <= 0x09 || val == 0x0a)
Rudolf Marek6af586d2006-06-12 22:00:53 +020087 vid = 1087500 - (val & 0x1f) * 25000;
Jean Delvared0f28272005-08-01 22:50:08 +020088 else
Rudolf Marek6af586d2006-06-12 22:00:53 +020089 vid = 1862500 - (val & 0x1f) * 25000;
Jean Delvared0f28272005-08-01 22:50:08 +020090 if(val & 0x20)
Rudolf Marek6af586d2006-06-12 22:00:53 +020091 vid -= 12500;
92 return((vid + 500) / 1000);
Jean Delvared0f28272005-08-01 22:50:08 +020093
Rudolf Marek6af586d2006-06-12 22:00:53 +020094 case 110: /* Intel Conroe */
95 /* compute in uV, round to mV */
96 val &= 0xff;
97 if(((val & 0x7e) == 0xfe) || (!(val & 0x7e)))
98 return 0;
99 return((1600000 - (val - 2) * 6250 + 500) / 1000);
Jean Delvared0f28272005-08-01 22:50:08 +0200100 case 24: /* Opteron processor */
Rudolf Marek177d1652006-04-25 14:24:46 +0200101 val &= 0x1f;
Jean Delvared0f28272005-08-01 22:50:08 +0200102 return(val == 0x1f ? 0 : 1550 - val * 25);
103
104 case 91: /* VRM 9.1 */
105 case 90: /* VRM 9.0 */
Rudolf Marek177d1652006-04-25 14:24:46 +0200106 val &= 0x1f;
Jean Delvared0f28272005-08-01 22:50:08 +0200107 return(val == 0x1f ? 0 :
108 1850 - val * 25);
109
110 case 85: /* VRM 8.5 */
Rudolf Marek177d1652006-04-25 14:24:46 +0200111 val &= 0x1f;
Jean Delvared0f28272005-08-01 22:50:08 +0200112 return((val & 0x10 ? 25 : 0) +
113 ((val & 0x0f) > 0x04 ? 2050 : 1250) -
114 ((val & 0x0f) * 50));
115
116 case 84: /* VRM 8.4 */
117 val &= 0x0f;
118 /* fall through */
Rudolf Marek734a12a2005-12-18 16:36:52 +0100119 case 82: /* VRM 8.2 */
Rudolf Marek177d1652006-04-25 14:24:46 +0200120 val &= 0x1f;
Jean Delvared0f28272005-08-01 22:50:08 +0200121 return(val == 0x1f ? 0 :
122 val & 0x10 ? 5100 - (val) * 100 :
123 2050 - (val) * 50);
Rudolf Marek734a12a2005-12-18 16:36:52 +0100124 case 17: /* Intel IMVP-II */
Rudolf Marek177d1652006-04-25 14:24:46 +0200125 val &= 0x1f;
Rudolf Marek734a12a2005-12-18 16:36:52 +0100126 return(val & 0x10 ? 975 - (val & 0xF) * 25 :
127 1750 - val * 50);
Jean Delvare4c537fb2006-02-05 23:21:05 +0100128 case 13:
Rudolf Marek177d1652006-04-25 14:24:46 +0200129 val &= 0x3f;
130 return(1708 - val * 16);
Rudolf Marek6af586d2006-06-12 22:00:53 +0200131 case 14: /* Intel Core */
132 /* compute in uV, round to mV */
133 val &= 0x7f;
134 return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
Rudolf Marek734a12a2005-12-18 16:36:52 +0100135 default: /* report 0 for unknown */
136 printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
137 return 0;
Jean Delvared0f28272005-08-01 22:50:08 +0200138 }
139}
140
141
142/*
143 After this point is the code to automatically determine which
144 VRM/VRD specification should be used depending on the CPU.
145*/
146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147struct vrm_model {
148 u8 vendor;
149 u8 eff_family;
150 u8 eff_model;
Rudolf Marek734a12a2005-12-18 16:36:52 +0100151 u8 eff_stepping;
152 u8 vrm_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153};
154
155#define ANY 0xFF
156
157#ifdef CONFIG_X86
158
Rudolf Marek734a12a2005-12-18 16:36:52 +0100159/* the stepping parameter is highest acceptable stepping for current line */
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161static struct vrm_model vrm_models[] = {
Rudolf Marek734a12a2005-12-18 16:36:52 +0100162 {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */
163 {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */
Jean Delvare4c537fb2006-02-05 23:21:05 +0100164 {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */
Rudolf Marek734a12a2005-12-18 16:36:52 +0100165 {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
Jean Delvare4c537fb2006-02-05 23:21:05 +0100166 {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */
Rudolf Marek6af586d2006-06-12 22:00:53 +0200167 {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */
168 {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */
Rudolf Marek734a12a2005-12-18 16:36:52 +0100169 {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */
170 {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */
171 {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */
172 {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */
173 {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */
174 {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */
175 {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0}, /* Itanium 2 */
176 {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */
177 {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */
178 {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */
179 {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M */
180 {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */
Jean Delvareda97a5a2005-07-31 21:54:28 +0200181};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
Rudolf Marek734a12a2005-12-18 16:36:52 +0100183static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184{
185 int i = 0;
186
187 while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
188 if (vrm_models[i].vendor==vendor)
Jean Delvareda97a5a2005-07-31 21:54:28 +0200189 if ((vrm_models[i].eff_family==eff_family)
190 && ((vrm_models[i].eff_model==eff_model) ||
Rudolf Marek734a12a2005-12-18 16:36:52 +0100191 (vrm_models[i].eff_model==ANY)) &&
192 (eff_stepping <= vrm_models[i].eff_stepping))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 return vrm_models[i].vrm_type;
194 i++;
195 }
196
197 return 0;
198}
199
Rudolf Marek734a12a2005-12-18 16:36:52 +0100200u8 vid_which_vrm(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 struct cpuinfo_x86 *c = cpu_data;
203 u32 eax;
Rudolf Marek734a12a2005-12-18 16:36:52 +0100204 u8 eff_family, eff_model, eff_stepping, vrm_ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Jean Delvareda97a5a2005-07-31 21:54:28 +0200206 if (c->x86 < 6) /* Any CPU with family lower than 6 */
207 return 0; /* doesn't have VID and/or CPUID */
208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 eax = cpuid_eax(1);
210 eff_family = ((eax & 0x00000F00)>>8);
211 eff_model = ((eax & 0x000000F0)>>4);
Rudolf Marek734a12a2005-12-18 16:36:52 +0100212 eff_stepping = eax & 0xF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 if (eff_family == 0xF) { /* use extended model & family */
214 eff_family += ((eax & 0x00F00000)>>20);
215 eff_model += ((eax & 0x000F0000)>>16)<<4;
216 }
Rudolf Marek734a12a2005-12-18 16:36:52 +0100217 vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 if (vrm_ret == 0)
Jean Delvareda97a5a2005-07-31 21:54:28 +0200219 printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
220 "x86 CPU\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 return vrm_ret;
222}
223
Rudolf Marek734a12a2005-12-18 16:36:52 +0100224/* and now for something completely different for the non-x86 world */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225#else
Rudolf Marek734a12a2005-12-18 16:36:52 +0100226u8 vid_which_vrm(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227{
Jean Delvare303760b2005-07-31 21:52:01 +0200228 printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 return 0;
230}
231#endif
232
Jean Delvared0f28272005-08-01 22:50:08 +0200233EXPORT_SYMBOL(vid_from_reg);
Jean Delvare303760b2005-07-31 21:52:01 +0200234EXPORT_SYMBOL(vid_which_vrm);
Jean Delvare96478ef2005-07-31 21:45:27 +0200235
236MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
237
Jean Delvare303760b2005-07-31 21:52:01 +0200238MODULE_DESCRIPTION("hwmon-vid driver");
Jean Delvare96478ef2005-07-31 21:45:27 +0200239MODULE_LICENSE("GPL");