aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/coretemp.c
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-05-27 15:20:19 -0400
committerGuenter Roeck <linux@roeck-us.net>2014-01-15 00:36:30 -0500
commit14513ee696a0cd12a19318e433b75a786808adc3 (patch)
tree1fd6688393ff985910f51d5036432c4d5aea906e /drivers/hwmon/coretemp.c
parentcd9bb0564c551f8a72763dd45590e9ea6787811e (diff)
hwmon: (coretemp) Use PCI host bridge ID to identify CPU if necessary
Atom S12x0 CPUs are identified by the CPU host bridge ID. Add an override table based on PCI IDs as well as code to detect it. PCI access functions can now be called with PCI disabled, so unlike previous attempts to use PCI IDs, the code no longer depends on it. If PCI is disabled, the CPU will not be identified correctly. Since it is unlikely that anything will work in this case, this is an acceptable limitation. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/coretemp.c')
-rw-r--r--drivers/hwmon/coretemp.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 942509892895..d84dae73203e 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -36,6 +36,7 @@
36#include <linux/cpu.h> 36#include <linux/cpu.h>
37#include <linux/smp.h> 37#include <linux/smp.h>
38#include <linux/moduleparam.h> 38#include <linux/moduleparam.h>
39#include <linux/pci.h>
39#include <asm/msr.h> 40#include <asm/msr.h>
40#include <asm/processor.h> 41#include <asm/processor.h>
41#include <asm/cpu_device_id.h> 42#include <asm/cpu_device_id.h>
@@ -190,6 +191,17 @@ static ssize_t show_temp(struct device *dev,
190 return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN; 191 return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN;
191} 192}
192 193
194struct tjmax_pci {
195 unsigned int device;
196 int tjmax;
197};
198
199static const struct tjmax_pci tjmax_pci_table[] = {
200 { 0x0c72, 102000 }, /* Atom S1240 (Centerton) */
201 { 0x0c73, 95000 }, /* Atom S1220 (Centerton) */
202 { 0x0c75, 95000 }, /* Atom S1260 (Centerton) */
203};
204
193struct tjmax { 205struct tjmax {
194 char const *id; 206 char const *id;
195 int tjmax; 207 int tjmax;
@@ -222,8 +234,11 @@ static const struct tjmax_model tjmax_model_table[] = {
222 * is undetectable by software 234 * is undetectable by software
223 */ 235 */
224 { 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */ 236 { 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */
225 { 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z2760) */ 237 { 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z27x0) */
226 { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */ 238 { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx)
239 * Also matches S12x0 (stepping 9), covered by
240 * PCI table
241 */
227}; 242};
228 243
229static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) 244static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
@@ -236,8 +251,20 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
236 int err; 251 int err;
237 u32 eax, edx; 252 u32 eax, edx;
238 int i; 253 int i;
254 struct pci_dev *host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
255
256 /*
257 * Explicit tjmax table entries override heuristics.
258 * First try PCI host bridge IDs, followed by model ID strings
259 * and model/stepping information.
260 */
261 if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) {
262 for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) {
263 if (host_bridge->device == tjmax_pci_table[i].device)
264 return tjmax_pci_table[i].tjmax;
265 }
266 }
239 267
240 /* explicit tjmax table entries override heuristics */
241 for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) { 268 for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) {
242 if (strstr(c->x86_model_id, tjmax_table[i].id)) 269 if (strstr(c->x86_model_id, tjmax_table[i].id))
243 return tjmax_table[i].tjmax; 270 return tjmax_table[i].tjmax;