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