aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/coretemp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-21 19:37:42 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-21 19:37:42 -0500
commitbfe38ccf8d0b541f387f65267f6f3794be59233a (patch)
treec1f5cece3247431b3d2c484da831d2eb0fd6c9e0 /drivers/hwmon/coretemp.c
parent20f8d2a49360980f1dc0afe2ea227e3ba887e575 (diff)
parent25e9c86d5a6d82ea45eb680fc66bf73ac5e50dff (diff)
Merge branch 'release' of git://lm-sensors.org/kernel/mhoffman/hwmon-2.6
* 'release' of git://lm-sensors.org/kernel/mhoffman/hwmon-2.6: hwmon: normal_i2c arrays should be const hwmon: New driver for Analog Devices ADT7473 sensor chip hwmon: (coretemp) Add Penryn CPU to coretemp hwmon: (coretemp) Add TjMax detection for mobile CPUs hwmon: (applesmc) sensors set for MacBook2 hwmon: (thmc50) Storage class should be before const qualifier hwmon: (coretemp) fix section mismatch warning hwmon: (coretemp) Add maximum cooling temperature readout hwmon: (adm1026) Properly terminate sysfs groups hwmon: (vt8231) Update maintainer email address hwmon: (vt8231) Add individual alarm files hwmon: (via686a) Add individual alarm files hwmon: (smsc47m1) Add individual alarm files hwmon: (max1619) Add individual alarm and fault files hwmon: (lm92) Add individual alarm files
Diffstat (limited to 'drivers/hwmon/coretemp.c')
-rw-r--r--drivers/hwmon/coretemp.c119
1 files changed, 82 insertions, 37 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 3ee60d26e3a2..70239acecc8e 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -38,7 +38,8 @@
38 38
39#define DRVNAME "coretemp" 39#define DRVNAME "coretemp"
40 40
41typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW; 41typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL,
42 SHOW_NAME } SHOW;
42 43
43/* 44/*
44 * Functions declaration 45 * Functions declaration
@@ -55,6 +56,7 @@ struct coretemp_data {
55 unsigned long last_updated; /* in jiffies */ 56 unsigned long last_updated; /* in jiffies */
56 int temp; 57 int temp;
57 int tjmax; 58 int tjmax;
59 int ttarget;
58 u8 alarm; 60 u8 alarm;
59}; 61};
60 62
@@ -93,9 +95,10 @@ static ssize_t show_temp(struct device *dev,
93 95
94 if (attr->index == SHOW_TEMP) 96 if (attr->index == SHOW_TEMP)
95 err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN; 97 err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
96 else 98 else if (attr->index == SHOW_TJMAX)
97 err = sprintf(buf, "%d\n", data->tjmax); 99 err = sprintf(buf, "%d\n", data->tjmax);
98 100 else
101 err = sprintf(buf, "%d\n", data->ttarget);
99 return err; 102 return err;
100} 103}
101 104
@@ -103,6 +106,8 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
103 SHOW_TEMP); 106 SHOW_TEMP);
104static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 107static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
105 SHOW_TJMAX); 108 SHOW_TJMAX);
109static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL,
110 SHOW_TTARGET);
106static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL); 111static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
107static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); 112static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
108static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME); 113static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
@@ -147,6 +152,56 @@ static struct coretemp_data *coretemp_update_device(struct device *dev)
147 return data; 152 return data;
148} 153}
149 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
150static int __devinit coretemp_probe(struct platform_device *pdev) 205static int __devinit coretemp_probe(struct platform_device *pdev)
151{ 206{
152 struct coretemp_data *data; 207 struct coretemp_data *data;
@@ -163,8 +218,6 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
163 data->id = pdev->id; 218 data->id = pdev->id;
164 data->name = "coretemp"; 219 data->name = "coretemp";
165 mutex_init(&data->update_lock); 220 mutex_init(&data->update_lock);
166 /* Tjmax default is 100 degrees C */
167 data->tjmax = 100000;
168 221
169 /* test if we can access the THERM_STATUS MSR */ 222 /* test if we can access the THERM_STATUS MSR */
170 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);
@@ -191,40 +244,29 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
191 } 244 }
192 } 245 }
193 246
194 /* Some processors have Tjmax 85 following magic should detect it 247 data->tjmax = adjust_tjmax(c, data->id, &pdev->dev);
195 Intel won't disclose the information without signed NDA, but 248 platform_set_drvdata(pdev, data);
196 individuals cannot sign it. Catch(ed) 22.
197 */
198 249
199 if (((c->x86_model == 0xf) && (c->x86_mask > 3)) || 250 /* read the still undocumented IA32_TEMPERATURE_TARGET it exists
200 (c->x86_model == 0xe)) { 251 on older CPUs but not in this register */
201 err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx); 252
253 if (c->x86_model > 0xe) {
254 err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx);
202 if (err) { 255 if (err) {
203 dev_warn(&pdev->dev, 256 dev_warn(&pdev->dev, "Unable to read"
204 "Unable to access MSR 0xEE, Tjmax left at %d " 257 " IA32_TEMPERATURE_TARGET MSR\n");
205 "degrees C\n", data->tjmax/1000); 258 } else {
206 } else if (eax & 0x40000000) { 259 data->ttarget = data->tjmax -
207 data->tjmax = 85000; 260 (((eax >> 8) & 0xff) * 1000);
261 err = device_create_file(&pdev->dev,
262 &sensor_dev_attr_temp1_max.dev_attr);
263 if (err)
264 goto exit_free;
208 } 265 }
209 } 266 }
210 267
211 /* Intel says that above should not work for desktop Core2 processors,
212 but it seems to work. There is no other way how get the absolute
213 readings. Warn the user about this. First check if are desktop,
214 bit 50 of MSR_IA32_PLATFORM_ID should be 0.
215 */
216
217 rdmsr_safe_on_cpu(data->id, MSR_IA32_PLATFORM_ID, &eax, &edx);
218
219 if ((c->x86_model == 0xf) && (!(edx & 0x00040000))) {
220 dev_warn(&pdev->dev, "Using undocumented features, absolute "
221 "temperature might be wrong!\n");
222 }
223
224 platform_set_drvdata(pdev, data);
225
226 if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group))) 268 if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
227 goto exit_free; 269 goto exit_dev;
228 270
229 data->hwmon_dev = hwmon_device_register(&pdev->dev); 271 data->hwmon_dev = hwmon_device_register(&pdev->dev);
230 if (IS_ERR(data->hwmon_dev)) { 272 if (IS_ERR(data->hwmon_dev)) {
@@ -238,6 +280,8 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
238 280
239exit_class: 281exit_class:
240 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); 282 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
283exit_dev:
284 device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
241exit_free: 285exit_free:
242 kfree(data); 286 kfree(data);
243exit: 287exit:
@@ -250,6 +294,7 @@ static int __devexit coretemp_remove(struct platform_device *pdev)
250 294
251 hwmon_device_unregister(data->hwmon_dev); 295 hwmon_device_unregister(data->hwmon_dev);
252 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); 296 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
297 device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
253 platform_set_drvdata(pdev, NULL); 298 platform_set_drvdata(pdev, NULL);
254 kfree(data); 299 kfree(data);
255 return 0; 300 return 0;
@@ -330,7 +375,7 @@ static void coretemp_device_remove(unsigned int cpu)
330 mutex_unlock(&pdev_list_mutex); 375 mutex_unlock(&pdev_list_mutex);
331} 376}
332 377
333static int coretemp_cpu_callback(struct notifier_block *nfb, 378static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb,
334 unsigned long action, void *hcpu) 379 unsigned long action, void *hcpu)
335{ 380{
336 unsigned int cpu = (unsigned long) hcpu; 381 unsigned int cpu = (unsigned long) hcpu;
@@ -347,7 +392,7 @@ static int coretemp_cpu_callback(struct notifier_block *nfb,
347 return NOTIFY_OK; 392 return NOTIFY_OK;
348} 393}
349 394
350static struct notifier_block coretemp_cpu_notifier = { 395static struct notifier_block coretemp_cpu_notifier __refdata = {
351 .notifier_call = coretemp_cpu_callback, 396 .notifier_call = coretemp_cpu_callback,
352}; 397};
353#endif /* !CONFIG_HOTPLUG_CPU */ 398#endif /* !CONFIG_HOTPLUG_CPU */
@@ -368,10 +413,10 @@ static int __init coretemp_init(void)
368 for_each_online_cpu(i) { 413 for_each_online_cpu(i) {
369 struct cpuinfo_x86 *c = &cpu_data(i); 414 struct cpuinfo_x86 *c = &cpu_data(i);
370 415
371 /* check if family 6, models e, f, 16 */ 416 /* check if family 6, models 0xe, 0xf, 0x16, 0x17 */
372 if ((c->cpuid_level < 0) || (c->x86 != 0x6) || 417 if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
373 !((c->x86_model == 0xe) || (c->x86_model == 0xf) || 418 !((c->x86_model == 0xe) || (c->x86_model == 0xf) ||
374 (c->x86_model == 0x16))) { 419 (c->x86_model == 0x16) || (c->x86_model == 0x17))) {
375 420
376 /* supported CPU not found, but report the unknown 421 /* supported CPU not found, but report the unknown
377 family 6 CPU */ 422 family 6 CPU */