xref: /linux/drivers/hwmon/hwmon-vid.c (revision 7188cc66)
1303760b4SJean Delvare /*
2303760b4SJean Delvare     hwmon-vid.c - VID/VRM/VRD voltage conversions
3303760b4SJean Delvare 
4*7188cc66SJean Delvare     Copyright (c) 2004 Rudolf Marek <r.marek@assembler.cz>
5303760b4SJean Delvare 
6d0f28270SJean Delvare     Partly imported from i2c-vid.h of the lm_sensors project
7d0f28270SJean Delvare     Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
8d0f28270SJean Delvare     With assistance from Trent Piepho <xyzzy@speakeasy.org>
9d0f28270SJean Delvare 
10303760b4SJean Delvare     This program is free software; you can redistribute it and/or modify
11303760b4SJean Delvare     it under the terms of the GNU General Public License as published by
12303760b4SJean Delvare     the Free Software Foundation; either version 2 of the License, or
13303760b4SJean Delvare     (at your option) any later version.
14303760b4SJean Delvare 
15303760b4SJean Delvare     This program is distributed in the hope that it will be useful,
16303760b4SJean Delvare     but WITHOUT ANY WARRANTY; without even the implied warranty of
17303760b4SJean Delvare     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18303760b4SJean Delvare     GNU General Public License for more details.
19303760b4SJean Delvare 
20303760b4SJean Delvare     You should have received a copy of the GNU General Public License
21303760b4SJean Delvare     along with this program; if not, write to the Free Software
22303760b4SJean Delvare     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23303760b4SJean Delvare */
24303760b4SJean Delvare 
25303760b4SJean Delvare #include <linux/module.h>
26303760b4SJean Delvare #include <linux/kernel.h>
27303760b4SJean Delvare #include <linux/hwmon-vid.h>
28303760b4SJean Delvare 
29d0f28270SJean Delvare /*
30d0f28270SJean Delvare     Common code for decoding VID pins.
31d0f28270SJean Delvare 
32d0f28270SJean Delvare     References:
33d0f28270SJean Delvare 
34d0f28270SJean Delvare     For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
35d0f28270SJean Delvare     available at http://developer.intel.com/.
36d0f28270SJean Delvare 
37d0f28270SJean Delvare     For VRD 10.0 and up, "VRD x.y Design Guide",
38d0f28270SJean Delvare     available at http://developer.intel.com/.
39d0f28270SJean Delvare 
40d0f28270SJean Delvare     AMD Opteron processors don't follow the Intel specifications.
41d0f28270SJean Delvare     I'm going to "make up" 2.4 as the spec number for the Opterons.
42d0f28270SJean Delvare     No good reason just a mnemonic for the 24x Opteron processor
43d0f28270SJean Delvare     series.
44d0f28270SJean Delvare 
45d0f28270SJean Delvare     Opteron VID encoding is:
46d0f28270SJean Delvare        00000  =  1.550 V
47d0f28270SJean Delvare        00001  =  1.525 V
48d0f28270SJean Delvare         . . . .
49d0f28270SJean Delvare        11110  =  0.800 V
50d0f28270SJean Delvare        11111  =  0.000 V (off)
51734a12a3SRudolf Marek 
52734a12a3SRudolf Marek     The 17 specification is in fact Intel Mobile Voltage Positioning -
53734a12a3SRudolf Marek     (IMVP-II). You can find more information in the datasheet of Max1718
54734a12a3SRudolf Marek     http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452
55734a12a3SRudolf Marek 
564c537fb2SJean Delvare     The 13 specification corresponds to the Intel Pentium M series. There
574c537fb2SJean Delvare     doesn't seem to be any named specification for these. The conversion
584c537fb2SJean Delvare     tables are detailed directly in the various Pentium M datasheets:
594c537fb2SJean Delvare     http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm
606af586dcSRudolf Marek 
616af586dcSRudolf Marek     The 14 specification corresponds to Intel Core series. There
626af586dcSRudolf Marek     doesn't seem to be any named specification for these. The conversion
636af586dcSRudolf Marek     tables are detailed directly in the various Pentium Core datasheets:
646af586dcSRudolf Marek     http://www.intel.com/design/mobile/datashts/309221.htm
656af586dcSRudolf Marek 
666af586dcSRudolf Marek     The 110 (VRM 11) specification corresponds to Intel Conroe based series.
676af586dcSRudolf Marek     http://www.intel.com/design/processor/applnots/313214.htm
68d0f28270SJean Delvare */
69d0f28270SJean Delvare 
70d0f28270SJean Delvare /* vrm is the VRM/VRD document version multiplied by 10.
716af586dcSRudolf Marek    val is the 4-bit or more VID code.
726af586dcSRudolf Marek    Returned value is in mV to avoid floating point in the kernel.
736af586dcSRudolf Marek    Some VID have some bits in uV scale, this is rounded to mV */
74734a12a3SRudolf Marek int vid_from_reg(int val, u8 vrm)
75d0f28270SJean Delvare {
76d0f28270SJean Delvare 	int vid;
77d0f28270SJean Delvare 
78d0f28270SJean Delvare 	switch(vrm) {
79d0f28270SJean Delvare 
80d0f28270SJean Delvare 	case 100:               /* VRD 10.0 */
816af586dcSRudolf Marek 		/* compute in uV, round to mV */
82177d165dSRudolf Marek 		val &= 0x3f;
83d0f28270SJean Delvare 		if((val & 0x1f) == 0x1f)
84d0f28270SJean Delvare 			return 0;
85d0f28270SJean Delvare 		if((val & 0x1f) <= 0x09 || val == 0x0a)
866af586dcSRudolf Marek 			vid = 1087500 - (val & 0x1f) * 25000;
87d0f28270SJean Delvare 		else
886af586dcSRudolf Marek 			vid = 1862500 - (val & 0x1f) * 25000;
89d0f28270SJean Delvare 		if(val & 0x20)
906af586dcSRudolf Marek 			vid -= 12500;
916af586dcSRudolf Marek 		return((vid + 500) / 1000);
92d0f28270SJean Delvare 
936af586dcSRudolf Marek 	case 110:		/* Intel Conroe */
946af586dcSRudolf Marek 				/* compute in uV, round to mV */
956af586dcSRudolf Marek 		val &= 0xff;
966af586dcSRudolf Marek 		if(((val & 0x7e) == 0xfe) || (!(val & 0x7e)))
976af586dcSRudolf Marek 			return 0;
986af586dcSRudolf Marek 		return((1600000 - (val - 2) * 6250 + 500) / 1000);
99d0f28270SJean Delvare 	case 24:                /* Opteron processor */
100177d165dSRudolf Marek 		val &= 0x1f;
101d0f28270SJean Delvare 		return(val == 0x1f ? 0 : 1550 - val * 25);
102d0f28270SJean Delvare 
103d0f28270SJean Delvare 	case 91:		/* VRM 9.1 */
104d0f28270SJean Delvare 	case 90:		/* VRM 9.0 */
105177d165dSRudolf Marek 		val &= 0x1f;
106d0f28270SJean Delvare 		return(val == 0x1f ? 0 :
107d0f28270SJean Delvare 		                       1850 - val * 25);
108d0f28270SJean Delvare 
109d0f28270SJean Delvare 	case 85:		/* VRM 8.5 */
110177d165dSRudolf Marek 		val &= 0x1f;
111d0f28270SJean Delvare 		return((val & 0x10  ? 25 : 0) +
112d0f28270SJean Delvare 		       ((val & 0x0f) > 0x04 ? 2050 : 1250) -
113d0f28270SJean Delvare 		       ((val & 0x0f) * 50));
114d0f28270SJean Delvare 
115d0f28270SJean Delvare 	case 84:		/* VRM 8.4 */
116d0f28270SJean Delvare 		val &= 0x0f;
117d0f28270SJean Delvare 				/* fall through */
118734a12a3SRudolf Marek 	case 82:		/* VRM 8.2 */
119177d165dSRudolf Marek 		val &= 0x1f;
120d0f28270SJean Delvare 		return(val == 0x1f ? 0 :
121d0f28270SJean Delvare 		       val & 0x10  ? 5100 - (val) * 100 :
122d0f28270SJean Delvare 		                     2050 - (val) * 50);
123734a12a3SRudolf Marek 	case 17:		/* Intel IMVP-II */
124177d165dSRudolf Marek 		val &= 0x1f;
125734a12a3SRudolf Marek 		return(val & 0x10 ? 975 - (val & 0xF) * 25 :
126734a12a3SRudolf Marek 				    1750 - val * 50);
1274c537fb2SJean Delvare 	case 13:
128177d165dSRudolf Marek 		val &= 0x3f;
129177d165dSRudolf Marek 		return(1708 - val * 16);
1306af586dcSRudolf Marek 	case 14:		/* Intel Core */
1316af586dcSRudolf Marek 				/* compute in uV, round to mV */
1326af586dcSRudolf Marek 		val &= 0x7f;
1336af586dcSRudolf Marek 		return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
134734a12a3SRudolf Marek 	default:		/* report 0 for unknown */
135734a12a3SRudolf Marek 		printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
136734a12a3SRudolf Marek 		return 0;
137d0f28270SJean Delvare 	}
138d0f28270SJean Delvare }
139d0f28270SJean Delvare 
140d0f28270SJean Delvare 
141d0f28270SJean Delvare /*
142d0f28270SJean Delvare     After this point is the code to automatically determine which
143d0f28270SJean Delvare     VRM/VRD specification should be used depending on the CPU.
144d0f28270SJean Delvare */
145d0f28270SJean Delvare 
146303760b4SJean Delvare struct vrm_model {
147303760b4SJean Delvare 	u8 vendor;
148303760b4SJean Delvare 	u8 eff_family;
149303760b4SJean Delvare 	u8 eff_model;
150734a12a3SRudolf Marek 	u8 eff_stepping;
151734a12a3SRudolf Marek 	u8 vrm_type;
152303760b4SJean Delvare };
153303760b4SJean Delvare 
154303760b4SJean Delvare #define ANY 0xFF
155303760b4SJean Delvare 
156303760b4SJean Delvare #ifdef CONFIG_X86
157303760b4SJean Delvare 
158734a12a3SRudolf Marek /* the stepping parameter is highest acceptable stepping for current line */
159734a12a3SRudolf Marek 
160303760b4SJean Delvare static struct vrm_model vrm_models[] = {
161734a12a3SRudolf Marek 	{X86_VENDOR_AMD, 0x6, ANY, ANY, 90},		/* Athlon Duron etc */
162734a12a3SRudolf Marek 	{X86_VENDOR_AMD, 0xF, ANY, ANY, 24},		/* Athlon 64, Opteron and above VRM 24 */
1634c537fb2SJean Delvare 	{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13},		/* Pentium M (130 nm) */
164734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85},		/* Tualatin */
1654c537fb2SJean Delvare 	{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13},		/* Pentium M (90 nm) */
1666af586dcSRudolf Marek 	{X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14},		/* Intel Core (65 nm) */
1676af586dcSRudolf Marek 	{X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110},		/* Intel Conroe */
168734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0x6, ANY, ANY, 82},		/* any P6 */
169734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0x7, ANY, ANY, 0},		/* Itanium */
170734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90},		/* P4 */
171734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90},		/* P4 Willamette */
172734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90},		/* P4 Northwood */
173734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0xF, ANY, ANY, 100},		/* Prescott and above assume VRD 10 */
174734a12a3SRudolf Marek 	{X86_VENDOR_INTEL, 0x10, ANY, ANY, 0},		/* Itanium 2 */
175734a12a3SRudolf Marek 	{X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85},	/* Eden ESP/Ezra */
176734a12a3SRudolf Marek 	{X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85},	/* Ezra T */
177734a12a3SRudolf Marek 	{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},	/* Nemiah */
178734a12a3SRudolf Marek 	{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},	/* C3-M */
179734a12a3SRudolf Marek 	{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0}		/* stop here */
180303760b4SJean Delvare };
181303760b4SJean Delvare 
182734a12a3SRudolf Marek static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
183303760b4SJean Delvare {
184303760b4SJean Delvare 	int i = 0;
185303760b4SJean Delvare 
186303760b4SJean Delvare 	while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
187303760b4SJean Delvare 		if (vrm_models[i].vendor==vendor)
188da97a5a3SJean Delvare 			if ((vrm_models[i].eff_family==eff_family)
189da97a5a3SJean Delvare 			 && ((vrm_models[i].eff_model==eff_model) ||
190734a12a3SRudolf Marek 			     (vrm_models[i].eff_model==ANY)) &&
191734a12a3SRudolf Marek 			     (eff_stepping <= vrm_models[i].eff_stepping))
192303760b4SJean Delvare 				return vrm_models[i].vrm_type;
193303760b4SJean Delvare 		i++;
194303760b4SJean Delvare 	}
195303760b4SJean Delvare 
196303760b4SJean Delvare 	return 0;
197303760b4SJean Delvare }
198303760b4SJean Delvare 
199734a12a3SRudolf Marek u8 vid_which_vrm(void)
200303760b4SJean Delvare {
201303760b4SJean Delvare 	struct cpuinfo_x86 *c = cpu_data;
202303760b4SJean Delvare 	u32 eax;
203734a12a3SRudolf Marek 	u8 eff_family, eff_model, eff_stepping, vrm_ret;
204303760b4SJean Delvare 
205da97a5a3SJean Delvare 	if (c->x86 < 6)		/* Any CPU with family lower than 6 */
206da97a5a3SJean Delvare 		return 0;	/* doesn't have VID and/or CPUID */
207da97a5a3SJean Delvare 
208303760b4SJean Delvare 	eax = cpuid_eax(1);
209303760b4SJean Delvare 	eff_family = ((eax & 0x00000F00)>>8);
210303760b4SJean Delvare 	eff_model  = ((eax & 0x000000F0)>>4);
211734a12a3SRudolf Marek 	eff_stepping = eax & 0xF;
212303760b4SJean Delvare 	if (eff_family == 0xF) {	/* use extended model & family */
213303760b4SJean Delvare 		eff_family += ((eax & 0x00F00000)>>20);
214303760b4SJean Delvare 		eff_model += ((eax & 0x000F0000)>>16)<<4;
215303760b4SJean Delvare 	}
216734a12a3SRudolf Marek 	vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
217303760b4SJean Delvare 	if (vrm_ret == 0)
218303760b4SJean Delvare 		printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
219303760b4SJean Delvare 		       "x86 CPU\n");
220303760b4SJean Delvare 	return vrm_ret;
221303760b4SJean Delvare }
222303760b4SJean Delvare 
223734a12a3SRudolf Marek /* and now for something completely different for the non-x86 world */
224303760b4SJean Delvare #else
225734a12a3SRudolf Marek u8 vid_which_vrm(void)
226303760b4SJean Delvare {
227303760b4SJean Delvare 	printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
228303760b4SJean Delvare 	return 0;
229303760b4SJean Delvare }
230303760b4SJean Delvare #endif
231303760b4SJean Delvare 
232d0f28270SJean Delvare EXPORT_SYMBOL(vid_from_reg);
233303760b4SJean Delvare EXPORT_SYMBOL(vid_which_vrm);
234303760b4SJean Delvare 
235*7188cc66SJean Delvare MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
236303760b4SJean Delvare 
237303760b4SJean Delvare MODULE_DESCRIPTION("hwmon-vid driver");
238303760b4SJean Delvare MODULE_LICENSE("GPL");
239