diff -pNaur -X b/Documentation/dontdiff a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig --- a/drivers/hwmon/Kconfig 2006-08-17 11:21:23.000000000 +0000 +++ b/drivers/hwmon/Kconfig 2006-08-17 23:35:38.000000000 +0000 @@ -507,6 +507,18 @@ config SENSORS_HDAPS Say Y here if you have an applicable laptop and want to experience the awesome power of hdaps. +config SENSORS_TSC2102 + tristate "TI TSC2102 battery & temperature sensors" + depends on HWMON && SPI_MASTER + select TSC2102 + help + Say Y if your board has a TSC2102 chip and you want to + have its battery state, auxiliary input and temperature + sensors exported through hwmon. + + This driver can also be built as a module. In this case + the module will be called tsc2102_sensors. + config HWMON_DEBUG_CHIP bool "Hardware Monitoring Chip debugging messages" depends on HWMON diff -pNaur -X b/Documentation/dontdiff a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile --- a/drivers/hwmon/Makefile 2006-08-17 11:21:23.000000000 +0000 +++ b/drivers/hwmon/Makefile 2006-08-17 23:46:01.000000000 +0000 @@ -48,6 +48,7 @@ obj-$(CONFIG_SENSORS_VIA686A) += via686a obj-$(CONFIG_SENSORS_VT8231) += vt8231.o obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o +obj-$(CONFIG_SENSORS_TSC2102) += tsc2102_sensors.o ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG diff -pNaur -X b/Documentation/dontdiff a/drivers/hwmon/tsc2102_sensors.c b/drivers/hwmon/tsc2102_sensors.c --- a/drivers/hwmon/tsc2102_sensors.c 1970-01-01 00:00:00.000000000 +0000 +++ b/drivers/hwmon/tsc2102_sensors.c 2006-08-17 23:35:38.000000000 +0000 @@ -0,0 +1,227 @@ +/* + * drivers/hwmon/tsc2102_sensors.c + * + * hwmon interface for TSC2102 sensors + * + * Copyright (c) 2005 Andrzej Zaborowski + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this package; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_APM +#include +#endif + +static struct tsc2102_hwmon { + struct class_device *dev; + int bat[2], aux, temp[2]; + struct mutex lock; + struct tsc2102_config *pdata; +} hwmon; + +static void tsc2102_ports(int bat1, int bat2, int aux) +{ + mutex_lock(&hwmon.lock); + hwmon.bat[0] = bat1; + hwmon.bat[1] = bat2; + hwmon.aux = aux; + mutex_unlock(&hwmon.lock); +} + +static void tsc2102_temp1(int temp) +{ + mutex_lock(&hwmon.lock); + hwmon.temp[0] = temp; + mutex_unlock(&hwmon.lock); +} + +static void tsc2102_temp2(int temp) +{ + mutex_lock(&hwmon.lock); + hwmon.temp[1] = temp; + mutex_unlock(&hwmon.lock); +} + +#define TSC2102_INPUT(devname, field) \ +static ssize_t show_ ## devname(struct device *dev, \ + struct device_attribute *devattr, char *buf) \ +{ \ + struct tsc2102_hwmon *devhwmon = dev_get_drvdata(dev); \ + int value; \ + mutex_lock(&devhwmon->lock); \ + value = devhwmon->field; \ + mutex_unlock(&devhwmon->lock); \ + return sprintf(buf, "%i\n", value); \ +} \ +static DEVICE_ATTR(devname ## _input, S_IRUGO, show_ ## devname, NULL); + +TSC2102_INPUT(in0, bat[0]) +TSC2102_INPUT(in1, bat[1]) +TSC2102_INPUT(in2, aux) + +static ssize_t show_temp1(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct tsc2102_hwmon *devhwmon = dev_get_drvdata(dev); + int t1, t2; +#ifndef TSC2102_TEMP_CALIBRATE + int value, diff; +#endif + + mutex_lock(&devhwmon->lock); + t1 = devhwmon->temp[0]; + t2 = devhwmon->temp[1]; + mutex_unlock(&devhwmon->lock); + +#ifndef TSC2102_TEMP_CALIBRATE + /* + * Use method #2 (differential) to calculate current temperature. + * The difference between TEMP2 and TEMP1 input values is + * multiplied by a constant to obtain current temperature. + * To find this constant we use the values measured at 25 C as + * thermometer calibration data. + * + * 2982 is 25 degrees Celcius represented in Kelvins and + * multiplied by 10 for fixed point precision (273.15 + 25). + * 2732 is zero degrees Celcius. + */ + diff = devhwmon->pdata->temp_at25c[1] - devhwmon->pdata->temp_at25c[0]; + BUG_ON(diff == 0); + value = (t2 - t1) * 2982 / diff; /* This is in Kelvins now */ + + t1 = (value - 2732) / 10; /* Celcius, integral part */ + t2 = (value - 2) % 10; /* Celcius, fraction part */ + return sprintf(buf, "%i.%i C\n", t1, t2); +#else + /* Show current unconverted values from chip */ + return sprintf(buf, "%i %i\n", t1, t2); +#endif +} +static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL); + +#ifdef CONFIG_APM +static void tsc2102_get_power_status(struct apm_power_info *info) +{ + mutex_lock(&hwmon.lock); + + hwmon.pdata->apm_report(info, hwmon.bat); + + mutex_unlock(&hwmon.lock); +} +#endif + +static int tsc2102_hwmon_probe(struct platform_device *pdev) +{ + struct tsc2102_config *pdata = pdev->dev.platform_data; + int status = 0; + + mutex_init(&hwmon.lock); + hwmon.dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(hwmon.dev)) { + printk(KERN_ERR "tsc2102_hwmon: Class registration failed\n"); + return PTR_ERR(hwmon.dev); + } + + hwmon.pdata = pdata; + +#ifdef CONFIG_APM + if (pdata->apm_report) + apm_get_power_status = tsc2102_get_power_status; +#endif + + platform_set_drvdata(pdev, &hwmon); + + if (pdata->monitor & (TSC_BAT1 | TSC_BAT2 | TSC_AUX)) + status |= tsc2102_ports_cb(tsc2102_ports); + if (pdata->monitor & TSC_TEMP) { + status |= tsc2102_temp1_cb(tsc2102_temp1); + status |= tsc2102_temp2_cb(tsc2102_temp2); + } + if (status) { + hwmon_device_unregister(hwmon.dev); + return status; + } + + if (pdata->monitor & TSC_BAT1) + device_create_file(&pdev->dev, &dev_attr_in0_input); + if (pdata->monitor & TSC_BAT2) + device_create_file(&pdev->dev, &dev_attr_in1_input); + if (pdata->monitor & TSC_AUX) + device_create_file(&pdev->dev, &dev_attr_in2_input); + if (pdata->monitor & TSC_TEMP) + device_create_file(&pdev->dev, &dev_attr_temp1_input); + + return 0; +} + +static int tsc2102_hwmon_remove(struct platform_device *pdev) +{ + struct tsc2102_hwmon *dev = platform_get_drvdata(pdev); + + tsc2102_ports_cb(0); + tsc2102_temp1_cb(0); + tsc2102_temp2_cb(0); + hwmon_device_unregister(dev->dev); + return 0; +} + +static int +tsc2102_hwmon_suspend(struct platform_device *pdev, pm_message_t state) +{ + return 0; +} + +static int tsc2102_hwmon_resume(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver tsc2102_hwmon_driver = { + .probe = tsc2102_hwmon_probe, + .remove = tsc2102_hwmon_remove, + .suspend = tsc2102_hwmon_suspend, + .resume = tsc2102_hwmon_resume, + .driver = { + .name = "tsc2102-hwmon", + }, +}; + +static int __init tsc2102_hwmon_init(void) +{ + if (platform_driver_register(&tsc2102_hwmon_driver)) + return -ENODEV; + + return 0; +} + +static void __exit tsc2102_hwmon_exit(void) +{ + platform_driver_unregister(&tsc2102_hwmon_driver); +} + +module_init(tsc2102_hwmon_init); +module_exit(tsc2102_hwmon_exit); + +MODULE_AUTHOR("Andrzej Zaborowski"); +MODULE_DESCRIPTION("hwmon driver for TI TSC2102 sensors."); +MODULE_LICENSE("GPL"); +#endif /* OMAP_ALSA_TSC2102_H_ */