diff options
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/coretemp.c | 83 |
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 | ||
155 | static 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 | |||
155 | static int __devinit coretemp_probe(struct platform_device *pdev) | 205 | static 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 |