aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/hwmon-vid.c69
-rw-r--r--include/linux/hwmon-vid.h6
2 files changed, 45 insertions, 30 deletions
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 312769ad4da..e497274916c 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -49,20 +49,22 @@
49 . . . . 49 . . . .
50 11110 = 0.800 V 50 11110 = 0.800 V
51 11111 = 0.000 V (off) 51 11111 = 0.000 V (off)
52
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
52*/ 57*/
53 58
54/* vrm is the VRM/VRD document version multiplied by 10. 59/* vrm is the VRM/VRD document version multiplied by 10.
55 val is the 4-, 5- or 6-bit VID code. 60 val is the 4-, 5- or 6-bit VID code.
56 Returned value is in mV to avoid floating point in the kernel. */ 61 Returned value is in mV to avoid floating point in the kernel. */
57int vid_from_reg(int val, int vrm) 62int vid_from_reg(int val, u8 vrm)
58{ 63{
59 int vid; 64 int vid;
60 65
61 switch(vrm) { 66 switch(vrm) {
62 67
63 case 0:
64 return 0;
65
66 case 100: /* VRD 10.0 */ 68 case 100: /* VRD 10.0 */
67 if((val & 0x1f) == 0x1f) 69 if((val & 0x1f) == 0x1f)
68 return 0; 70 return 0;
@@ -91,10 +93,16 @@ int vid_from_reg(int val, int vrm)
91 case 84: /* VRM 8.4 */ 93 case 84: /* VRM 8.4 */
92 val &= 0x0f; 94 val &= 0x0f;
93 /* fall through */ 95 /* fall through */
94 default: /* VRM 8.2 */ 96 case 82: /* VRM 8.2 */
95 return(val == 0x1f ? 0 : 97 return(val == 0x1f ? 0 :
96 val & 0x10 ? 5100 - (val) * 100 : 98 val & 0x10 ? 5100 - (val) * 100 :
97 2050 - (val) * 50); 99 2050 - (val) * 50);
100 case 17: /* Intel IMVP-II */
101 return(val & 0x10 ? 975 - (val & 0xF) * 25 :
102 1750 - val * 50);
103 default: /* report 0 for unknown */
104 printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
105 return 0;
98 } 106 }
99} 107}
100 108
@@ -108,30 +116,36 @@ struct vrm_model {
108 u8 vendor; 116 u8 vendor;
109 u8 eff_family; 117 u8 eff_family;
110 u8 eff_model; 118 u8 eff_model;
111 int vrm_type; 119 u8 eff_stepping;
120 u8 vrm_type;
112}; 121};
113 122
114#define ANY 0xFF 123#define ANY 0xFF
115 124
116#ifdef CONFIG_X86 125#ifdef CONFIG_X86
117 126
127/* the stepping parameter is highest acceptable stepping for current line */
128
118static struct vrm_model vrm_models[] = { 129static struct vrm_model vrm_models[] = {
119 {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */ 130 {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */
120 {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */ 131 {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */
121 {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */ 132 {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */
122 {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* Tualatin */ 133 {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
123 {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */ 134 {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */
124 {X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */ 135 {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */
125 {X86_VENDOR_INTEL, 0xF, 0x0, 90}, /* P4 */ 136 {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */
126 {X86_VENDOR_INTEL, 0xF, 0x1, 90}, /* P4 Willamette */ 137 {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */
127 {X86_VENDOR_INTEL, 0xF, 0x2, 90}, /* P4 Northwood */ 138 {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */
128 {X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */ 139 {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */
129 {X86_VENDOR_INTEL, 0xF, 0x4, 100}, /* P4 Prescott */ 140 {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0}, /* Itanium 2 */
130 {X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */ 141 {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */
131 {X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */ 142 {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */
143 {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */
144 {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M */
145 {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */
132}; 146};
133 147
134static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor) 148static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
135{ 149{
136 int i = 0; 150 int i = 0;
137 151
@@ -139,7 +153,8 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
139 if (vrm_models[i].vendor==vendor) 153 if (vrm_models[i].vendor==vendor)
140 if ((vrm_models[i].eff_family==eff_family) 154 if ((vrm_models[i].eff_family==eff_family)
141 && ((vrm_models[i].eff_model==eff_model) || 155 && ((vrm_models[i].eff_model==eff_model) ||
142 (vrm_models[i].eff_model==ANY))) 156 (vrm_models[i].eff_model==ANY)) &&
157 (eff_stepping <= vrm_models[i].eff_stepping))
143 return vrm_models[i].vrm_type; 158 return vrm_models[i].vrm_type;
144 i++; 159 i++;
145 } 160 }
@@ -147,12 +162,11 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
147 return 0; 162 return 0;
148} 163}
149 164
150int vid_which_vrm(void) 165u8 vid_which_vrm(void)
151{ 166{
152 struct cpuinfo_x86 *c = cpu_data; 167 struct cpuinfo_x86 *c = cpu_data;
153 u32 eax; 168 u32 eax;
154 u8 eff_family, eff_model; 169 u8 eff_family, eff_model, eff_stepping, vrm_ret;
155 int vrm_ret;
156 170
157 if (c->x86 < 6) /* Any CPU with family lower than 6 */ 171 if (c->x86 < 6) /* Any CPU with family lower than 6 */
158 return 0; /* doesn't have VID and/or CPUID */ 172 return 0; /* doesn't have VID and/or CPUID */
@@ -160,20 +174,21 @@ int vid_which_vrm(void)
160 eax = cpuid_eax(1); 174 eax = cpuid_eax(1);
161 eff_family = ((eax & 0x00000F00)>>8); 175 eff_family = ((eax & 0x00000F00)>>8);
162 eff_model = ((eax & 0x000000F0)>>4); 176 eff_model = ((eax & 0x000000F0)>>4);
177 eff_stepping = eax & 0xF;
163 if (eff_family == 0xF) { /* use extended model & family */ 178 if (eff_family == 0xF) { /* use extended model & family */
164 eff_family += ((eax & 0x00F00000)>>20); 179 eff_family += ((eax & 0x00F00000)>>20);
165 eff_model += ((eax & 0x000F0000)>>16)<<4; 180 eff_model += ((eax & 0x000F0000)>>16)<<4;
166 } 181 }
167 vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor); 182 vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
168 if (vrm_ret == 0) 183 if (vrm_ret == 0)
169 printk(KERN_INFO "hwmon-vid: Unknown VRM version of your " 184 printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
170 "x86 CPU\n"); 185 "x86 CPU\n");
171 return vrm_ret; 186 return vrm_ret;
172} 187}
173 188
174/* and now something completely different for the non-x86 world */ 189/* and now for something completely different for the non-x86 world */
175#else 190#else
176int vid_which_vrm(void) 191u8 vid_which_vrm(void)
177{ 192{
178 printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n"); 193 printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
179 return 0; 194 return 0;
diff --git a/include/linux/hwmon-vid.h b/include/linux/hwmon-vid.h
index cd4b7a042b8..f346e4d5381 100644
--- a/include/linux/hwmon-vid.h
+++ b/include/linux/hwmon-vid.h
@@ -23,14 +23,14 @@
23#ifndef _LINUX_HWMON_VID_H 23#ifndef _LINUX_HWMON_VID_H
24#define _LINUX_HWMON_VID_H 24#define _LINUX_HWMON_VID_H
25 25
26int vid_from_reg(int val, int vrm); 26int vid_from_reg(int val, u8 vrm);
27int vid_which_vrm(void); 27u8 vid_which_vrm(void);
28 28
29/* vrm is the VRM/VRD document version multiplied by 10. 29/* vrm is the VRM/VRD document version multiplied by 10.
30 val is in mV to avoid floating point in the kernel. 30 val is in mV to avoid floating point in the kernel.
31 Returned value is the 4-, 5- or 6-bit VID code. 31 Returned value is the 4-, 5- or 6-bit VID code.
32 Note that only VRM 9.x is supported for now. */ 32 Note that only VRM 9.x is supported for now. */
33static inline int vid_to_reg(int val, int vrm) 33static inline int vid_to_reg(int val, u8 vrm)
34{ 34{
35 switch (vrm) { 35 switch (vrm) {
36 case 91: /* VRM 9.1 */ 36 case 91: /* VRM 9.1 */