aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/thinkpad-acpi.txt26
-rw-r--r--drivers/misc/thinkpad_acpi.c122
-rw-r--r--drivers/misc/thinkpad_acpi.h2
3 files changed, 143 insertions, 7 deletions
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt
index cc079afaf66b..80c0bf28e392 100644
--- a/Documentation/thinkpad-acpi.txt
+++ b/Documentation/thinkpad-acpi.txt
@@ -458,17 +458,17 @@ X40:
458 16 - one medium-pitched beep repeating constantly, stop with 17 458 16 - one medium-pitched beep repeating constantly, stop with 17
459 17 - stop 16 459 17 - stop 16
460 460
461Temperature sensors -- /proc/acpi/ibm/thermal 461Temperature sensors
462--------------------------------------------- 462-------------------
463
464procfs: /proc/acpi/ibm/thermal
465sysfs device attributes: (hwmon) temp*_input
463 466
464Most ThinkPads include six or more separate temperature sensors but 467Most ThinkPads include six or more separate temperature sensors but
465only expose the CPU temperature through the standard ACPI methods. 468only expose the CPU temperature through the standard ACPI methods.
466This feature shows readings from up to eight different sensors on older 469This feature shows readings from up to eight different sensors on older
467ThinkPads, and it has experimental support for up to sixteen different 470ThinkPads, and it has experimental support for up to sixteen different
468sensors on newer ThinkPads. Readings from sensors that are not available 471sensors on newer ThinkPads.
469return -128.
470
471No commands can be written to this file.
472 472
473EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the 473EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the
474implementation directly accesses hardware registers and may not work as 474implementation directly accesses hardware registers and may not work as
@@ -525,6 +525,20 @@ The A31 has a very atypical layout for the thermal sensors
5258: Bay Battery: secondary sensor 5258: Bay Battery: secondary sensor
526 526
527 527
528Procfs notes:
529 Readings from sensors that are not available return -128.
530 No commands can be written to this file.
531
532Sysfs notes:
533 Sensors that are not available return the ENXIO error. This
534 status may change at runtime, as there are hotplug thermal
535 sensors, like those inside the batteries and docks.
536
537 thinkpad-acpi thermal sensors are reported through the hwmon
538 subsystem, and follow all of the hwmon guidelines at
539 Documentation/hwmon.
540
541
528EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump 542EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
529------------------------------------------------------------------------ 543------------------------------------------------------------------------
530 544
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index aa69ff0c1c91..d5526e882ddd 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -1992,11 +1992,91 @@ static struct ibm_struct beep_driver_data = {
1992 1992
1993static enum thermal_access_mode thermal_read_mode; 1993static enum thermal_access_mode thermal_read_mode;
1994 1994
1995/* sysfs temp##_input -------------------------------------------------- */
1996
1997static ssize_t thermal_temp_input_show(struct device *dev,
1998 struct device_attribute *attr,
1999 char *buf)
2000{
2001 struct sensor_device_attribute *sensor_attr =
2002 to_sensor_dev_attr(attr);
2003 int idx = sensor_attr->index;
2004 s32 value;
2005 int res;
2006
2007 res = thermal_get_sensor(idx, &value);
2008 if (res)
2009 return res;
2010 if (value == TP_EC_THERMAL_TMP_NA * 1000)
2011 return -ENXIO;
2012
2013 return snprintf(buf, PAGE_SIZE, "%d\n", value);
2014}
2015
2016#define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \
2017 SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, thermal_temp_input_show, NULL, _idxB)
2018
2019static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = {
2020 THERMAL_SENSOR_ATTR_TEMP(1, 0),
2021 THERMAL_SENSOR_ATTR_TEMP(2, 1),
2022 THERMAL_SENSOR_ATTR_TEMP(3, 2),
2023 THERMAL_SENSOR_ATTR_TEMP(4, 3),
2024 THERMAL_SENSOR_ATTR_TEMP(5, 4),
2025 THERMAL_SENSOR_ATTR_TEMP(6, 5),
2026 THERMAL_SENSOR_ATTR_TEMP(7, 6),
2027 THERMAL_SENSOR_ATTR_TEMP(8, 7),
2028 THERMAL_SENSOR_ATTR_TEMP(9, 8),
2029 THERMAL_SENSOR_ATTR_TEMP(10, 9),
2030 THERMAL_SENSOR_ATTR_TEMP(11, 10),
2031 THERMAL_SENSOR_ATTR_TEMP(12, 11),
2032 THERMAL_SENSOR_ATTR_TEMP(13, 12),
2033 THERMAL_SENSOR_ATTR_TEMP(14, 13),
2034 THERMAL_SENSOR_ATTR_TEMP(15, 14),
2035 THERMAL_SENSOR_ATTR_TEMP(16, 15),
2036};
2037
2038#define THERMAL_ATTRS(X) \
2039 &sensor_dev_attr_thermal_temp_input[X].dev_attr.attr
2040
2041static struct attribute *thermal_temp_input_attr[] = {
2042 THERMAL_ATTRS(8),
2043 THERMAL_ATTRS(9),
2044 THERMAL_ATTRS(10),
2045 THERMAL_ATTRS(11),
2046 THERMAL_ATTRS(12),
2047 THERMAL_ATTRS(13),
2048 THERMAL_ATTRS(14),
2049 THERMAL_ATTRS(15),
2050 THERMAL_ATTRS(0),
2051 THERMAL_ATTRS(1),
2052 THERMAL_ATTRS(2),
2053 THERMAL_ATTRS(3),
2054 THERMAL_ATTRS(4),
2055 THERMAL_ATTRS(5),
2056 THERMAL_ATTRS(6),
2057 THERMAL_ATTRS(7),
2058 NULL
2059};
2060
2061static const struct attribute_group thermal_temp_input16_group = {
2062 .attrs = thermal_temp_input_attr
2063};
2064
2065static const struct attribute_group thermal_temp_input8_group = {
2066 .attrs = &thermal_temp_input_attr[8]
2067};
2068
2069#undef THERMAL_SENSOR_ATTR_TEMP
2070#undef THERMAL_ATTRS
2071
2072/* --------------------------------------------------------------------- */
2073
1995static int __init thermal_init(struct ibm_init_struct *iibm) 2074static int __init thermal_init(struct ibm_init_struct *iibm)
1996{ 2075{
1997 u8 t, ta1, ta2; 2076 u8 t, ta1, ta2;
1998 int i; 2077 int i;
1999 int acpi_tmp7; 2078 int acpi_tmp7;
2079 int res;
2000 2080
2001 vdbg_printk(TPACPI_DBG_INIT, "initializing thermal subdriver\n"); 2081 vdbg_printk(TPACPI_DBG_INIT, "initializing thermal subdriver\n");
2002 2082
@@ -2060,7 +2140,46 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
2060 str_supported(thermal_read_mode != TPACPI_THERMAL_NONE), 2140 str_supported(thermal_read_mode != TPACPI_THERMAL_NONE),
2061 thermal_read_mode); 2141 thermal_read_mode);
2062 2142
2063 return (thermal_read_mode != TPACPI_THERMAL_NONE)? 0 : 1; 2143 switch(thermal_read_mode) {
2144 case TPACPI_THERMAL_TPEC_16:
2145 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
2146 &thermal_temp_input16_group);
2147 if (res)
2148 return res;
2149 break;
2150 case TPACPI_THERMAL_TPEC_8:
2151 case TPACPI_THERMAL_ACPI_TMP07:
2152 case TPACPI_THERMAL_ACPI_UPDT:
2153 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
2154 &thermal_temp_input8_group);
2155 if (res)
2156 return res;
2157 break;
2158 case TPACPI_THERMAL_NONE:
2159 default:
2160 return 1;
2161 }
2162
2163 return 0;
2164}
2165
2166static void thermal_exit(void)
2167{
2168 switch(thermal_read_mode) {
2169 case TPACPI_THERMAL_TPEC_16:
2170 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
2171 &thermal_temp_input16_group);
2172 break;
2173 case TPACPI_THERMAL_TPEC_8:
2174 case TPACPI_THERMAL_ACPI_TMP07:
2175 case TPACPI_THERMAL_ACPI_UPDT:
2176 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
2177 &thermal_temp_input16_group);
2178 break;
2179 case TPACPI_THERMAL_NONE:
2180 default:
2181 break;
2182 }
2064} 2183}
2065 2184
2066/* idx is zero-based */ 2185/* idx is zero-based */
@@ -2168,6 +2287,7 @@ static int thermal_read(char *p)
2168static struct ibm_struct thermal_driver_data = { 2287static struct ibm_struct thermal_driver_data = {
2169 .name = "thermal", 2288 .name = "thermal",
2170 .read = thermal_read, 2289 .read = thermal_read,
2290 .exit = thermal_exit,
2171}; 2291};
2172 2292
2173/************************************************************************* 2293/*************************************************************************
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index a9feb53c6d3c..e833ff3caf39 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -38,6 +38,7 @@
38#include <linux/fb.h> 38#include <linux/fb.h>
39#include <linux/platform_device.h> 39#include <linux/platform_device.h>
40#include <linux/hwmon.h> 40#include <linux/hwmon.h>
41#include <linux/hwmon-sysfs.h>
41#include <asm/uaccess.h> 42#include <asm/uaccess.h>
42 43
43#include <linux/dmi.h> 44#include <linux/dmi.h>
@@ -467,6 +468,7 @@ enum thermal_access_mode {
467enum { /* TPACPI_THERMAL_TPEC_* */ 468enum { /* TPACPI_THERMAL_TPEC_* */
468 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ 469 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */
469 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ 470 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */
471 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */
470}; 472};
471 473
472#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ 474#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */