aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2006-11-24 08:47:08 -0500
committerLen Brown <len.brown@intel.com>2006-12-07 01:38:38 -0500
commit60eb0b35a9cc3400251cb4028d100e350649cf8a (patch)
tree2f655a273572e46b6c4f662071d027e57cad1bcf
parenta26f878abcd0491906b5bbac8dd174f27019e907 (diff)
ACPI: ibm-acpi: Implement direct-ec-access thermal reading modes for up to 16 sensors
This patch extends ibm-acpi to support reading thermal sensors directly through ACPI EC register access. It uses a DMI match to detect ThinkPads with a new-style embedded controller, that are known to have forward- compatible register maps and use 0x00 to fill in non-used registers and export thermal sensors at EC offsets 0x78-7F and 0xC0-C7. Direct ACPI EC register access is implemented for 8-sensor and 16-sensor new-style ThinkPad controller firmwares as an experimental feature. The code does some limited sanity checks on the temperatures read through EC access, and will default to the old ACPI TMP0-7 mode if anything is amiss. Userspace ABI is not changed for 8 sensors, but /proc/acpi/ibm/thermal is extended for 16 sensors if the firmware supports 16 sensors. A documentation update is also provided. The information about the ThinkPad register map was determined by studying ibm-acpi "ecdump" output from various ThinkPad models, submitted by subscribers of the linux-thinkpad mailinglist. Futher information was gathered from the DSDT tables, as they describe the EC register map in recent ThinkPads. DSDT source shows that TMP0-7 access and direct register access are actually the same thing on these firmwares, but unfortunately IBM never did update their DSDT EC register map to export TMP8-TMP15 for the second range of sensors. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
-rw-r--r--Documentation/ibm-acpi.txt55
-rw-r--r--drivers/acpi/ibm_acpi.c93
2 files changed, 134 insertions, 14 deletions
diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt
index e50595bfd8ea..30f09e7a423e 100644
--- a/Documentation/ibm-acpi.txt
+++ b/Documentation/ibm-acpi.txt
@@ -398,25 +398,56 @@ Temperature sensors -- /proc/acpi/ibm/thermal
398 398
399Most ThinkPads include six or more separate temperature sensors but 399Most ThinkPads include six or more separate temperature sensors but
400only expose the CPU temperature through the standard ACPI methods. 400only expose the CPU temperature through the standard ACPI methods.
401This feature shows readings from up to eight different sensors. Some 401This feature shows readings from up to eight different sensors on older
402readings may not be valid, e.g. may show large negative values. For 402ThinkPads, and it has experimental support for up to sixteen different
403example, on the X40, a typical output may be: 403sensors on newer ThinkPads. Readings from sensors that are not available
404return -128.
404 405
406No commands can be written to this file.
407
408EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the
409implementation directly accesses hardware registers and may not work as
410expected. USE WITH CAUTION! To use this feature, you need to supply the
411experimental=1 parameter when loading the module. When EXPERIMENTAL
412mode is enabled, reading the first 8 sensors on newer ThinkPads will
413also use an new experimental thermal sensor access mode.
414
415For example, on the X40, a typical output may be:
405temperatures: 42 42 45 41 36 -128 33 -128 416temperatures: 42 42 45 41 36 -128 33 -128
406 417
407Thomas Gruber took his R51 apart and traced all six active sensors in 418EXPERIMENTAL: On the T43/p, a typical output may be:
408his laptop (the location of sensors may vary on other models): 419temperatures: 48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -128
420
421The mapping of thermal sensors to physical locations varies depending on
422system-board model (and thus, on ThinkPad model).
423
424http://thinkwiki.org/wiki/Thermal_Sensors is a public wiki page that
425tries to track down these locations for various models.
426
427Most (newer?) models seem to follow this pattern:
409 428
4101: CPU 4291: CPU
4112: Mini PCI Module 4302: (depends on model)
4123: HDD 4313: (depends on model)
4134: GPU 4324: GPU
4145: Battery 4335: Main battery: main sensor
4156: N/A 4346: Bay battery: main sensor
4167: Battery 4357: Main battery: secondary sensor
4178: N/A 4368: Bay battery: secondary sensor
4379-15: (depends on model)
438
439For the R51 (source: Thomas Gruber):
4402: Mini-PCI
4413: Internal HDD
442
443For the T43, T43/p (source: Shmidoax/Thinkwiki.org)
444http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_T43.2C_T43p
4452: System board, left side (near PCMCIA slot), reported as HDAPS temp
4463: PCMCIA slot
4479: MCH (northbridge) to DRAM Bus
44810: ICH (southbridge), under Mini-PCI card, under touchpad
44911: Power regulator, underside of system board, below F2 key
418 450
419No commands can be written to this file.
420 451
421EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump 452EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
422------------------------------------------------------------------------ 453------------------------------------------------------------------------
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index baf9492f0a79..1703c617c0e8 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -80,6 +80,7 @@
80#include <linux/proc_fs.h> 80#include <linux/proc_fs.h>
81#include <linux/backlight.h> 81#include <linux/backlight.h>
82#include <asm/uaccess.h> 82#include <asm/uaccess.h>
83#include <linux/dmi.h>
83 84
84#include <acpi/acpi_drivers.h> 85#include <acpi/acpi_drivers.h>
85#include <acpi/acnamesp.h> 86#include <acpi/acnamesp.h>
@@ -221,13 +222,17 @@ enum thermal_access_mode {
221 IBMACPI_THERMAL_NONE = 0, /* No thermal support */ 222 IBMACPI_THERMAL_NONE = 0, /* No thermal support */
222 IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */ 223 IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */
223 IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */ 224 IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */
225 IBMACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */
226 IBMACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */
224}; 227};
225 228
226#define IBMACPI_MAX_THERMAL_SENSORS 8 /* Max thermal sensors supported */ 229#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
227struct ibm_thermal_sensors_struct { 230struct ibm_thermal_sensors_struct {
228 s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; 231 s32 temp[IBMACPI_MAX_THERMAL_SENSORS];
229}; 232};
230 233
234static int ibm_thinkpad_ec_found;
235
231struct ibm_struct { 236struct ibm_struct {
232 char *name; 237 char *name;
233 char param[32]; 238 char param[32];
@@ -1290,7 +1295,52 @@ static enum thermal_access_mode thermal_read_mode;
1290 1295
1291static int thermal_init(void) 1296static int thermal_init(void)
1292{ 1297{
1293 if (acpi_evalf(ec_handle, NULL, "TMP7", "qv")) { 1298 u8 t, ta1, ta2;
1299 int i;
1300 int acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
1301
1302 if (ibm_thinkpad_ec_found && experimental) {
1303 /*
1304 * Direct EC access mode: sensors at registers
1305 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
1306 * non-implemented, thermal sensors return 0x80 when
1307 * not available
1308 */
1309
1310 ta1 = ta2 = 0;
1311 for (i = 0; i < 8; i++) {
1312 if (likely(acpi_ec_read(0x78 + i, &t))) {
1313 ta1 |= t;
1314 } else {
1315 ta1 = 0;
1316 break;
1317 }
1318 if (likely(acpi_ec_read(0xC0 + i, &t))) {
1319 ta2 |= t;
1320 } else {
1321 ta1 = 0;
1322 break;
1323 }
1324 }
1325 if (ta1 == 0) {
1326 /* This is sheer paranoia, but we handle it anyway */
1327 if (acpi_tmp7) {
1328 printk(IBM_ERR
1329 "ThinkPad ACPI EC access misbehaving, "
1330 "falling back to ACPI TMPx access mode\n");
1331 thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
1332 } else {
1333 printk(IBM_ERR
1334 "ThinkPad ACPI EC access misbehaving, "
1335 "disabling thermal sensors access\n");
1336 thermal_read_mode = IBMACPI_THERMAL_NONE;
1337 }
1338 } else {
1339 thermal_read_mode =
1340 (ta2 != 0) ?
1341 IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8;
1342 }
1343 } else if (acpi_tmp7) {
1294 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) { 1344 if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
1295 /* 600e/x, 770e, 770x */ 1345 /* 600e/x, 770e, 770x */
1296 thermal_read_mode = IBMACPI_THERMAL_ACPI_UPDT; 1346 thermal_read_mode = IBMACPI_THERMAL_ACPI_UPDT;
@@ -1309,12 +1359,30 @@ static int thermal_init(void)
1309static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) 1359static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
1310{ 1360{
1311 int i, t; 1361 int i, t;
1362 s8 tmp;
1312 char tmpi[] = "TMPi"; 1363 char tmpi[] = "TMPi";
1313 1364
1314 if (!s) 1365 if (!s)
1315 return -EINVAL; 1366 return -EINVAL;
1316 1367
1317 switch (thermal_read_mode) { 1368 switch (thermal_read_mode) {
1369#if IBMACPI_MAX_THERMAL_SENSORS >= 16
1370 case IBMACPI_THERMAL_TPEC_16:
1371 for (i = 0; i < 8; i++) {
1372 if (!acpi_ec_read(0xC0 + i, &tmp))
1373 return -EIO;
1374 s->temp[i + 8] = tmp * 1000;
1375 }
1376 /* fallthrough */
1377#endif
1378 case IBMACPI_THERMAL_TPEC_8:
1379 for (i = 0; i < 8; i++) {
1380 if (!acpi_ec_read(0x78 + i, &tmp))
1381 return -EIO;
1382 s->temp[i] = tmp * 1000;
1383 }
1384 return (thermal_read_mode == IBMACPI_THERMAL_TPEC_16) ? 16 : 8;
1385
1318 case IBMACPI_THERMAL_ACPI_UPDT: 1386 case IBMACPI_THERMAL_ACPI_UPDT:
1319 if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) 1387 if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
1320 return -EIO; 1388 return -EIO;
@@ -2052,6 +2120,24 @@ static void acpi_ibm_exit(void)
2052 remove_proc_entry(IBM_DIR, acpi_root_dir); 2120 remove_proc_entry(IBM_DIR, acpi_root_dir);
2053} 2121}
2054 2122
2123static int __init check_dmi_for_ec(void)
2124{
2125 struct dmi_device *dev = NULL;
2126
2127 /*
2128 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
2129 * X32 or newer, all Z series; Some models must have an
2130 * up-to-date BIOS or they will not be detected.
2131 *
2132 * See http://thinkwiki.org/wiki/List_of_DMI_IDs
2133 */
2134 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
2135 if (strstr(dev->name, "IBM ThinkPad Embedded Controller"))
2136 return 1;
2137 }
2138 return 0;
2139}
2140
2055static int __init acpi_ibm_init(void) 2141static int __init acpi_ibm_init(void)
2056{ 2142{
2057 int ret, i; 2143 int ret, i;
@@ -2071,6 +2157,9 @@ static int __init acpi_ibm_init(void)
2071 return -ENODEV; 2157 return -ENODEV;
2072 } 2158 }
2073 2159
2160 /* Models with newer firmware report the EC in DMI */
2161 ibm_thinkpad_ec_found = check_dmi_for_ec();
2162
2074 /* these handles are not required */ 2163 /* these handles are not required */
2075 IBM_HANDLE_INIT(vid); 2164 IBM_HANDLE_INIT(vid);
2076 IBM_HANDLE_INIT(vid2); 2165 IBM_HANDLE_INIT(vid2);