aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/coretemp.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index cbd047eac5b4..1f34ad84c557 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -152,6 +152,56 @@ static struct coretemp_data *coretemp_update_device(struct device *dev)
152 return data; 152 return data;
153} 153}
154 154
155static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
156{
157 /* The 100C is default for both mobile and non mobile CPUs */
158
159 int tjmax = 100000;
160 int ismobile = 1;
161 int err;
162 u32 eax, edx;
163
164 /* Early chips have no MSR for TjMax */
165
166 if ((c->x86_model == 0xf) && (c->x86_mask < 4)) {
167 ismobile = 0;
168 }
169
170 if ((c->x86_model > 0xe) && (ismobile)) {
171
172 /* Now we can detect the mobile CPU using Intel provided table
173 http://softwarecommunity.intel.com/Wiki/Mobility/720.htm
174 For Core2 cores, check MSR 0x17, bit 28 1 = Mobile CPU
175 */
176
177 err = rdmsr_safe_on_cpu(id, 0x17, &eax, &edx);
178 if (err) {
179 dev_warn(dev,
180 "Unable to access MSR 0x17, assuming desktop"
181 " CPU\n");
182 ismobile = 0;
183 } else if (!(eax & 0x10000000)) {
184 ismobile = 0;
185 }
186 }
187
188 if (ismobile) {
189
190 err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx);
191 if (err) {
192 dev_warn(dev,
193 "Unable to access MSR 0xEE, for Tjmax, left"
194 " at default");
195 } else if (eax & 0x40000000) {
196 tjmax = 85000;
197 }
198 } else {
199 dev_warn(dev, "Using relative temperature scale!\n");
200 }
201
202 return tjmax;
203}
204
155static int __devinit coretemp_probe(struct platform_device *pdev) 205static int __devinit coretemp_probe(struct platform_device *pdev)
156{ 206{
157 struct coretemp_data *data; 207 struct coretemp_data *data;
@@ -168,8 +218,6 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
168 data->id = pdev->id; 218 data->id = pdev->id;
169 data->name = "coretemp"; 219 data->name = "coretemp";
170 mutex_init(&data->update_lock); 220 mutex_init(&data->update_lock);
171 /* Tjmax default is 100 degrees C */
172 data->tjmax = 100000;
173 221
174 /* test if we can access the THERM_STATUS MSR */ 222 /* test if we can access the THERM_STATUS MSR */
175 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); 223 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
@@ -196,36 +244,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
196 } 244 }
197 } 245 }
198 246
199 /* Some processors have Tjmax 85 following magic should detect it 247 data->tjmax = adjust_tjmax(c, data->id, &pdev->dev);
200 Intel won't disclose the information without signed NDA, but
201 individuals cannot sign it. Catch(ed) 22.
202 */
203
204 if (((c->x86_model == 0xf) && (c->x86_mask > 3)) ||
205 (c->x86_model == 0xe)) {
206 err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx);
207 if (err) {
208 dev_warn(&pdev->dev,
209 "Unable to access MSR 0xEE, Tjmax left at %d "
210 "degrees C\n", data->tjmax/1000);
211 } else if (eax & 0x40000000) {
212 data->tjmax = 85000;
213 }
214 }
215
216 /* Intel says that above should not work for desktop Core2 processors,
217 but it seems to work. There is no other way how get the absolute
218 readings. Warn the user about this. First check if are desktop,
219 bit 50 of MSR_IA32_PLATFORM_ID should be 0.
220 */
221
222 rdmsr_safe_on_cpu(data->id, MSR_IA32_PLATFORM_ID, &eax, &edx);
223
224 if ((c->x86_model == 0xf) && (!(edx & 0x00040000))) {
225 dev_warn(&pdev->dev, "Using undocumented features, absolute "
226 "temperature might be wrong!\n");
227 }
228
229 platform_set_drvdata(pdev, data); 248 platform_set_drvdata(pdev, data);
230 249
231 /* read the still undocumented IA32_TEMPERATURE_TARGET it exists 250 /* read the still undocumented IA32_TEMPERATURE_TARGET it exists