diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-02-01 08:16:22 +0300 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-02-01 08:16:22 +0300 |
commit | a1f3d4bba8ea395a39d34ade6017afee8be16031 (patch) | |
tree | 874d843d35622f17aa6c3e048e42cf0d679bcb75 /drivers/hwmon | |
parent | 723d928417bffff6467da155d8ebbbe016464012 (diff) | |
parent | ebf53826e105f488f4f628703a108e98940d1dc5 (diff) | |
download | linux-a1f3d4bba8ea395a39d34ade6017afee8be16031.tar.xz |
Merge commit 'v2.6.38-rc3' into next
Diffstat (limited to 'drivers/hwmon')
55 files changed, 2311 insertions, 1796 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index a56f6adf3b76..773e484f1646 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -274,6 +274,16 @@ config SENSORS_ATXP1 This driver can also be built as a module. If so, the module will be called atxp1. +config SENSORS_DS620 + tristate "Dallas Semiconductor DS620" + depends on I2C + help + If you say yes here you get support for Dallas Semiconductor + DS620 sensor chip. + + This driver can also be built as a module. If so, the module + will be called ds620. + config SENSORS_DS1621 tristate "Dallas Semiconductor DS1621 and DS1625" depends on I2C @@ -608,8 +618,8 @@ config SENSORS_LM93 depends on I2C select HWMON_VID help - If you say yes here you get support for National Semiconductor LM93 - sensor chips. + If you say yes here you get support for National Semiconductor LM93, + LM94, and compatible sensor chips. This driver can also be built as a module. If so, the module will be called lm93. @@ -734,6 +744,16 @@ config SENSORS_SHT15 This driver can also be built as a module. If so, the module will be called sht15. +config SENSORS_SHT21 + tristate "Sensiron humidity and temperature sensors. SHT21 and compat." + depends on I2C + help + If you say yes here you get support for the Sensiron SHT21, SHT25 + humidity and temperature sensors. + + This driver can also be built as a module. If so, the module + will be called sht21. + config SENSORS_S3C tristate "Samsung built-in ADC" depends on S3C_ADC @@ -789,10 +809,10 @@ config SENSORS_DME1737 will be called dme1737. config SENSORS_EMC1403 - tristate "SMSC EMC1403 thermal sensor" + tristate "SMSC EMC1403/23 thermal sensor" depends on I2C help - If you say yes here you get support for the SMSC EMC1403 + If you say yes here you get support for the SMSC EMC1403/23 temperature monitoring chip. Threshold values can be configured using sysfs. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 2479b3da272c..dde02d99c238 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o obj-$(CONFIG_SENSORS_DME1737) += dme1737.o +obj-$(CONFIG_SENSORS_DS620) += ds620.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o @@ -90,6 +91,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o obj-$(CONFIG_SENSORS_SHT15) += sht15.o +obj-$(CONFIG_SENSORS_SHT21) += sht21.o obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SMM665) += smm665.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index 03694cc17a32..8f07a9dda152 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -20,6 +20,9 @@ the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because of lack of specs the CPU/RAM voltage & frequency control is not supported! */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/sched.h> #include <linux/init.h> @@ -220,6 +223,10 @@ struct abituguru_data { u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5]; }; +static const char *never_happen = "This should never happen."; +static const char *report_this = + "Please report this to the abituguru maintainer (see MAINTAINERS)"; + /* wait till the uguru is in the specified state */ static int abituguru_wait(struct abituguru_data *data, u8 state) { @@ -438,8 +445,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, /* Test val is sane / usable for sensor type detection. */ if ((val < 10u) || (val > 250u)) { - printk(KERN_WARNING ABIT_UGURU_NAME - ": bank1-sensor: %d reading (%d) too close to limits, " + pr_warn("bank1-sensor: %d reading (%d) too close to limits, " "unable to determine sensor type, skipping sensor\n", (int)sensor_addr, (int)val); /* assume no sensor is there for sensors for which we can't @@ -535,10 +541,8 @@ abituguru_detect_bank1_sensor_type_exit: 3) == 3) break; if (i == 3) { - printk(KERN_ERR ABIT_UGURU_NAME - ": Fatal error could not restore original settings. " - "This should never happen please report this to the " - "abituguru maintainer (see MAINTAINERS)\n"); + pr_err("Fatal error could not restore original settings. %s %s\n", + never_happen, report_this); return -ENODEV; } return ret; @@ -1268,14 +1272,12 @@ static int __devinit abituguru_probe(struct platform_device *pdev) } /* Fail safe check, this should never happen! */ if (sysfs_names_free < 0) { - printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of " - "space for sysfs attr names. This should never " - "happen please report to the abituguru maintainer " - "(see MAINTAINERS)\n"); + pr_err("Fatal error ran out of space for sysfs attr names. %s %s", + never_happen, report_this); res = -ENAMETOOLONG; goto abituguru_probe_error; } - printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n"); + pr_info("found Abit uGuru\n"); /* Register sysfs hooks */ for (i = 0; i < sysfs_attr_i; i++) @@ -1432,8 +1434,7 @@ static int __init abituguru_detect(void) "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); if (force) { - printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is " - "present because of \"force\" parameter\n"); + pr_info("Assuming Abit uGuru is present because of \"force\" parameter\n"); return ABIT_UGURU_BASE; } @@ -1467,8 +1468,7 @@ static int __init abituguru_init(void) abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address); if (!abituguru_pdev) { - printk(KERN_ERR ABIT_UGURU_NAME - ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); err = -ENOMEM; goto exit_driver_unregister; } @@ -1479,15 +1479,13 @@ static int __init abituguru_init(void) err = platform_device_add_resources(abituguru_pdev, &res, 1); if (err) { - printk(KERN_ERR ABIT_UGURU_NAME - ": Device resource addition failed (%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(abituguru_pdev); if (err) { - printk(KERN_ERR ABIT_UGURU_NAME - ": Device addition failed (%d)\n", err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index 3cf28af614b5..48d21e22e930 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -23,6 +23,9 @@ chip found on newer Abit uGuru motherboards. Note: because of lack of specs only reading the sensors and their settings is supported. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -608,6 +611,9 @@ static int verbose = 1; module_param(verbose, bool, 0644); MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting"); +static const char *never_happen = "This should never happen."; +static const char *report_this = + "Please report this to the abituguru3 maintainer (see MAINTAINERS)"; /* wait while the uguru is busy (usually after a write) */ static int abituguru3_wait_while_busy(struct abituguru3_data *data) @@ -940,15 +946,13 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) if (abituguru3_motherboards[i].id == id) break; if (!abituguru3_motherboards[i].id) { - printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard " - "ID: %04X. Please report this to the abituguru3 " - "maintainer (see MAINTAINERS)\n", (unsigned int)id); + pr_err("error unknown motherboard ID: %04X. %s\n", + (unsigned int)id, report_this); goto abituguru3_probe_error; } data->sensors = abituguru3_motherboards[i].sensors; - printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard " - "ID: %04X\n", (unsigned int)id); + pr_info("found Abit uGuru3, motherboard ID: %04X\n", (unsigned int)id); /* Fill the sysfs attr array */ sysfs_attr_i = 0; @@ -957,11 +961,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) for (i = 0; data->sensors[i].name; i++) { /* Fail safe check, this should never happen! */ if (i >= ABIT_UGURU3_MAX_NO_SENSORS) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Fatal error motherboard has more sensors " - "then ABIT_UGURU3_MAX_NO_SENSORS. This should " - "never happen please report to the abituguru3 " - "maintainer (see MAINTAINERS)\n"); + pr_err("Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s\n", + never_happen, report_this); res = -ENAMETOOLONG; goto abituguru3_probe_error; } @@ -983,10 +984,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) } /* Fail safe check, this should never happen! */ if (sysfs_names_free < 0) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Fatal error ran out of space for sysfs attr names. " - "This should never happen please report to the " - "abituguru3 maintainer (see MAINTAINERS)\n"); + pr_err("Fatal error ran out of space for sysfs attr names. %s %s\n", + never_happen, report_this); res = -ENAMETOOLONG; goto abituguru3_probe_error; } @@ -1189,8 +1188,7 @@ static int __init abituguru3_detect(void) "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); if (force) { - printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is " - "present because of \"force\" parameter\n"); + pr_info("Assuming Abit uGuru3 is present because of \"force\" parameter\n"); return 0; } @@ -1219,10 +1217,8 @@ static int __init abituguru3_init(void) return err; #ifdef CONFIG_DMI - printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was " - "not detected using DMI. Please send the output of " - "\"dmidecode\" to the abituguru3 maintainer " - "(see MAINTAINERS)\n"); + pr_warn("this motherboard was not detected using DMI. " + "Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n"); #endif } @@ -1233,8 +1229,7 @@ static int __init abituguru3_init(void) abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, ABIT_UGURU3_BASE); if (!abituguru3_pdev) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); err = -ENOMEM; goto exit_driver_unregister; } @@ -1245,15 +1240,13 @@ static int __init abituguru3_init(void) err = platform_device_add_resources(abituguru3_pdev, &res, 1); if (err) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Device resource addition failed (%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(abituguru3_pdev); if (err) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Device addition failed (%d)\n", err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index 1e4c21fc1a89..86d822aa9bbf 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -178,11 +178,13 @@ static int ad7414_probe(struct i2c_client *client, { struct ad7414_data *data; int conf; - int err = 0; + int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA)) + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + err = -EOPNOTSUPP; goto exit; + } data = kzalloc(sizeof(struct ad7414_data), GFP_KERNEL); if (!data) { diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 4bf969c0a32b..be0fdd58aa29 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -916,27 +916,27 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); - int val, orig_div, new_div, shift; + int val, orig_div, new_div; val = simple_strtol(buf, NULL, 10); new_div = DIV_TO_REG(val); - if (new_div == 0) { - return -EINVAL; - } + mutex_lock(&data->update_lock); orig_div = data->fan_div[nr]; data->fan_div[nr] = DIV_FROM_REG(new_div); if (nr < 4) { /* 0 <= nr < 4 */ - shift = 2 * nr; adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3, - ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) | - (new_div << shift))); + (DIV_TO_REG(data->fan_div[0]) << 0) | + (DIV_TO_REG(data->fan_div[1]) << 2) | + (DIV_TO_REG(data->fan_div[2]) << 4) | + (DIV_TO_REG(data->fan_div[3]) << 6)); } else { /* 3 < nr < 8 */ - shift = 2 * (nr - 4); adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7, - ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) | - (new_div << shift))); + (DIV_TO_REG(data->fan_div[4]) << 0) | + (DIV_TO_REG(data->fan_div[5]) << 2) | + (DIV_TO_REG(data->fan_div[6]) << 4) | + (DIV_TO_REG(data->fan_div[7]) << 6)); } if (data->fan_div[nr] != orig_div) { diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 0727ad250793..9e234b981b83 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -20,7 +20,7 @@ * Alarms 16-bit map of active alarms * Analog Out 0..1250 mV output * - * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear' + * Chassis Intrusion: clear CI latch with 'echo 0 > intrusion0_alarm' * * Test hardware: Intel SE440BX-2 desktop motherboard --Grant * @@ -476,13 +476,16 @@ static ssize_t set_aout(struct device *dev, static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); /* chassis_clear */ -static ssize_t chassis_clear(struct device *dev, +static ssize_t chassis_clear_legacy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); unsigned long val = simple_strtol(buf, NULL, 10); + dev_warn(dev, "Attribute chassis_clear is deprecated, " + "use intrusion0_alarm instead\n"); + if (val == 1) { i2c_smbus_write_byte_data(client, ADM9240_REG_CHASSIS_CLEAR, 0x80); @@ -490,7 +493,29 @@ static ssize_t chassis_clear(struct device *dev, } return count; } -static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear); +static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear_legacy); + +static ssize_t chassis_clear(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val; + + if (strict_strtoul(buf, 10, &val) || val != 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(client, ADM9240_REG_CHASSIS_CLEAR, 0x80); + data->valid = 0; /* Force cache refresh */ + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "chassis intrusion latch cleared\n"); + + return count; +} +static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm, + chassis_clear, 12); static struct attribute *adm9240_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, @@ -532,6 +557,7 @@ static struct attribute *adm9240_attributes[] = { &dev_attr_alarms.attr, &dev_attr_aout_output.attr, &dev_attr_chassis_clear.attr, + &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, &dev_attr_cpu0_vid.attr, NULL }; diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index aac85f3aed50..c42c5a69a664 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -4,7 +4,7 @@ This driver is based on the lm75 and other lm_sensors/hwmon drivers - Written by Steve Hardy <steve@linuxrealtime.co.uk> + Written by Steve Hardy <shardy@redhat.com> Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf @@ -271,7 +271,7 @@ static void __exit sensors_ads7828_exit(void) i2c_del_driver(&ads7828_driver); } -MODULE_AUTHOR("Steve Hardy <steve@linuxrealtime.co.uk>"); +MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>"); MODULE_DESCRIPTION("ADS7828 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 9e775717abb7..c6d1ce059aea 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -19,6 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/jiffies.h> #include <linux/i2c.h> @@ -274,7 +276,7 @@ static int adt7470_read_temperatures(struct i2c_client *client, i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]); if (res) { - printk(KERN_ERR "ha ha, interrupted"); + pr_err("ha ha, interrupted\n"); return -EAGAIN; } @@ -1286,8 +1288,10 @@ static int adt7470_probe(struct i2c_client *client, init_completion(&data->auto_update_stop); data->auto_update = kthread_run(adt7470_update_thread, client, dev_name(data->hwmon_dev)); - if (IS_ERR(data->auto_update)) + if (IS_ERR(data->auto_update)) { + err = PTR_ERR(data->auto_update); goto exit_unregister; + } return 0; diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c index fa9708c2d723..4033974d1bb3 100644 --- a/drivers/hwmon/amc6821.c +++ b/drivers/hwmon/amc6821.c @@ -4,7 +4,7 @@ Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si> Based on max6650.c: - Copyright (C) 2007 Hans J. Koch <hjk@linutronix.de> + Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index b6598aa557a0..4c0743660e9c 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -4,6 +4,7 @@ * computers. * * Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch> + * Copyright (C) 2010 Henrik Rydberg <rydberg@euromail.se> * * Based on hdaps.c driver: * Copyright (C) 2005 Robert Love <rml@novell.com> @@ -26,10 +27,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/input-polldev.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/timer.h> #include <linux/dmi.h> @@ -49,6 +53,7 @@ #define APPLESMC_MAX_DATA_LENGTH 32 +/* wait up to 32 ms for a status change. */ #define APPLESMC_MIN_WAIT 0x0040 #define APPLESMC_MAX_WAIT 0x8000 @@ -73,104 +78,15 @@ #define FANS_COUNT "FNum" /* r-o ui8 */ #define FANS_MANUAL "FS! " /* r-w ui16 */ -#define FAN_ACTUAL_SPEED "F0Ac" /* r-o fpe2 (2 bytes) */ -#define FAN_MIN_SPEED "F0Mn" /* r-o fpe2 (2 bytes) */ -#define FAN_MAX_SPEED "F0Mx" /* r-o fpe2 (2 bytes) */ -#define FAN_SAFE_SPEED "F0Sf" /* r-o fpe2 (2 bytes) */ -#define FAN_TARGET_SPEED "F0Tg" /* r-w fpe2 (2 bytes) */ -#define FAN_POSITION "F0ID" /* r-o char[16] */ - -/* - * Temperature sensors keys (sp78 - 2 bytes). - */ -static const char *temperature_sensors_sets[][41] = { -/* Set 0: Macbook Pro */ - { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H", - "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL }, -/* Set 1: Macbook2 set */ - { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "TTF0", "Th0H", - "Th0S", "Th1H", NULL }, -/* Set 2: Macbook set */ - { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S", - "Th1H", "Ts0P", NULL }, -/* Set 3: Macmini set */ - { "TC0D", "TC0P", NULL }, -/* Set 4: Mac Pro (2 x Quad-Core) */ - { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P", - "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P", - "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", - "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", - "TM9S", "TN0H", "TS0C", NULL }, -/* Set 5: iMac */ - { "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P", - "Tp0C", NULL }, -/* Set 6: Macbook3 set */ - { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H", - "Th0S", "Th1H", NULL }, -/* Set 7: Macbook Air */ - { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP", - "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL }, -/* Set 8: Macbook Pro 4,1 (Penryn) */ - { "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H", - "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, -/* Set 9: Macbook Pro 3,1 (Santa Rosa) */ - { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", - "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, -/* Set 10: iMac 5,1 */ - { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL }, -/* Set 11: Macbook 5,1 */ - { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P", - "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL }, -/* Set 12: Macbook Pro 5,1 */ - { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D", - "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0", - "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL }, -/* Set 13: iMac 8,1 */ - { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", - "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL }, -/* Set 14: iMac 6,1 */ - { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", - "TO0P", "Tp0P", NULL }, -/* Set 15: MacBook Air 2,1 */ - { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0", - "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P", - "Ts0S", NULL }, -/* Set 16: Mac Pro 3,1 (2 x Quad-Core) */ - { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P", - "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "TH0P", "TH1P", - "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", "TM1P", - "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S", - "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S", - NULL }, -/* Set 17: iMac 9,1 */ - { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TH0P", "TL0P", - "TN0D", "TN0H", "TN0P", "TO0P", "Tm0P", "Tp0P", NULL }, -/* Set 18: MacBook Pro 2,2 */ - { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0", - "Th0H", "Th1H", "Tm0P", "Ts0P", NULL }, -/* Set 19: Macbook Pro 5,3 */ - { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D", - "TG0F", "TG0H", "TG0P", "TG0T", "TN0D", "TN0P", "TTF0", "Th2H", - "Tm0P", "Ts0P", "Ts0S", NULL }, -/* Set 20: MacBook Pro 5,4 */ - { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TN0D", - "TN0P", "TTF0", "Th2H", "Ts0P", "Ts0S", NULL }, -/* Set 21: MacBook Pro 6,2 */ - { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", "TC0P", "TC1C", "TG0D", - "TG0P", "TG0T", "TMCD", "TP0P", "TPCD", "Th1H", "Th2H", "Tm0P", - "Ts0P", "Ts0S", NULL }, -/* Set 22: MacBook Pro 7,1 */ - { "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", "TN0D", "TN0P", "TN0S", - "TN1D", "TN1F", "TN1G", "TN1S", "Th1H", "Ts0P", "Ts0S", NULL }, -}; +#define FAN_ID_FMT "F%dID" /* r-o char[16] */ /* List of keys used to read/write fan speeds */ -static const char* fan_speed_keys[] = { - FAN_ACTUAL_SPEED, - FAN_MIN_SPEED, - FAN_MAX_SPEED, - FAN_SAFE_SPEED, - FAN_TARGET_SPEED +static const char *const fan_speed_fmt[] = { + "F%dAc", /* actual speed */ + "F%dMn", /* minimum speed (rw) */ + "F%dMx", /* maximum speed */ + "F%dSf", /* safe speed - not all models */ + "F%dTg", /* target speed (manual: rw) */ }; #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ @@ -184,14 +100,48 @@ static const char* fan_speed_keys[] = { #define SENSOR_Y 1 #define SENSOR_Z 2 -/* Structure to be passed to DMI_MATCH function */ -struct dmi_match_data { -/* Indicates whether this computer has an accelerometer. */ - int accelerometer; -/* Indicates whether this computer has light sensors and keyboard backlight. */ - int light; -/* Indicates which temperature sensors set to use. */ - int temperature_set; +#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff) +#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16) + +/* Dynamic device node attributes */ +struct applesmc_dev_attr { + struct sensor_device_attribute sda; /* hwmon attributes */ + char name[32]; /* room for node file name */ +}; + +/* Dynamic device node group */ +struct applesmc_node_group { + char *format; /* format string */ + void *show; /* show function */ + void *store; /* store function */ + int option; /* function argument */ + struct applesmc_dev_attr *nodes; /* dynamic node array */ +}; + +/* AppleSMC entry - cached register information */ +struct applesmc_entry { + char key[5]; /* four-letter key code */ + u8 valid; /* set when entry is successfully read once */ + u8 len; /* bounded by APPLESMC_MAX_DATA_LENGTH */ + char type[5]; /* four-letter type code */ + u8 flags; /* 0x10: func; 0x40: write; 0x80: read */ +}; + +/* Register lookup and registers common to all SMCs */ +static struct applesmc_registers { + struct mutex mutex; /* register read/write mutex */ + unsigned int key_count; /* number of SMC registers */ + unsigned int fan_count; /* number of fans */ + unsigned int temp_count; /* number of temperature registers */ + unsigned int temp_begin; /* temperature lower index bound */ + unsigned int temp_end; /* temperature upper index bound */ + int num_light_sensors; /* number of light sensors */ + bool has_accelerometer; /* has motion sensor */ + bool has_key_backlight; /* has keyboard backlight */ + bool init_complete; /* true when fully initialized */ + struct applesmc_entry *cache; /* cached key entries */ +} smcreg = { + .mutex = __MUTEX_INITIALIZER(smcreg.mutex), }; static const int debug; @@ -203,20 +153,6 @@ static u8 backlight_state[2]; static struct device *hwmon_dev; static struct input_polled_dev *applesmc_idev; -/* Indicates whether this computer has an accelerometer. */ -static unsigned int applesmc_accelerometer; - -/* Indicates whether this computer has light sensors and keyboard backlight. */ -static unsigned int applesmc_light; - -/* The number of fans handled by the driver */ -static unsigned int fans_handled; - -/* Indicates which temperature sensors set to use. */ -static unsigned int applesmc_temperature_set; - -static DEFINE_MUTEX(applesmc_lock); - /* * Last index written to key_at_index sysfs file, and value to use for all other * key_at_index_* sysfs files. @@ -238,18 +174,10 @@ static int __wait_status(u8 val) for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { udelay(us); - if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) { - if (debug) - printk(KERN_DEBUG - "Waited %d us for status %x\n", - 2 * us - APPLESMC_MIN_WAIT, val); + if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) return 0; - } } - printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n", - val, inb(APPLESMC_CMD_PORT)); - return -EIO; } @@ -267,159 +195,242 @@ static int send_command(u8 cmd) if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) return 0; } - printk(KERN_WARNING "applesmc: command failed: %x -> %x\n", - cmd, inb(APPLESMC_CMD_PORT)); return -EIO; } -/* - * applesmc_read_key - reads len bytes from a given key, and put them in buffer. - * Returns zero on success or a negative error on failure. Callers must - * hold applesmc_lock. - */ -static int applesmc_read_key(const char* key, u8* buffer, u8 len) +static int send_argument(const char *key) { int i; - if (len > APPLESMC_MAX_DATA_LENGTH) { - printk(KERN_ERR "applesmc_read_key: cannot read more than " - "%d bytes\n", APPLESMC_MAX_DATA_LENGTH); - return -EINVAL; - } - - if (send_command(APPLESMC_READ_CMD)) - return -EIO; - for (i = 0; i < 4; i++) { outb(key[i], APPLESMC_DATA_PORT); if (__wait_status(0x04)) return -EIO; } - if (debug) - printk(KERN_DEBUG "<%s", key); + return 0; +} + +static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) +{ + int i; + + if (send_command(cmd) || send_argument(key)) { + pr_warn("%s: read arg fail\n", key); + return -EIO; + } outb(len, APPLESMC_DATA_PORT); - if (debug) - printk(KERN_DEBUG ">%x", len); for (i = 0; i < len; i++) { - if (__wait_status(0x05)) + if (__wait_status(0x05)) { + pr_warn("%s: read data fail\n", key); return -EIO; + } buffer[i] = inb(APPLESMC_DATA_PORT); - if (debug) - printk(KERN_DEBUG "<%x", buffer[i]); } - if (debug) - printk(KERN_DEBUG "\n"); return 0; } -/* - * applesmc_write_key - writes len bytes from buffer to a given key. - * Returns zero on success or a negative error on failure. Callers must - * hold applesmc_lock. - */ -static int applesmc_write_key(const char* key, u8* buffer, u8 len) +static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) { int i; - if (len > APPLESMC_MAX_DATA_LENGTH) { - printk(KERN_ERR "applesmc_write_key: cannot write more than " - "%d bytes\n", APPLESMC_MAX_DATA_LENGTH); - return -EINVAL; - } - - if (send_command(APPLESMC_WRITE_CMD)) + if (send_command(cmd) || send_argument(key)) { + pr_warn("%s: write arg fail\n", key); return -EIO; - - for (i = 0; i < 4; i++) { - outb(key[i], APPLESMC_DATA_PORT); - if (__wait_status(0x04)) - return -EIO; } outb(len, APPLESMC_DATA_PORT); for (i = 0; i < len; i++) { - if (__wait_status(0x04)) + if (__wait_status(0x04)) { + pr_warn("%s: write data fail\n", key); return -EIO; + } outb(buffer[i], APPLESMC_DATA_PORT); } return 0; } +static int read_register_count(unsigned int *count) +{ + __be32 be; + int ret; + + ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); + if (ret) + return ret; + + *count = be32_to_cpu(be); + return 0; +} + /* - * applesmc_get_key_at_index - get key at index, and put the result in key - * (char[6]). Returns zero on success or a negative error on failure. Callers - * must hold applesmc_lock. + * Serialized I/O + * + * Returns zero on success or a negative error on failure. + * All functions below are concurrency safe - callers should NOT hold lock. */ -static int applesmc_get_key_at_index(int index, char* key) + +static int applesmc_read_entry(const struct applesmc_entry *entry, + u8 *buf, u8 len) { - int i; - u8 readkey[4]; - readkey[0] = index >> 24; - readkey[1] = index >> 16; - readkey[2] = index >> 8; - readkey[3] = index; + int ret; - if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD)) - return -EIO; + if (entry->len != len) + return -EINVAL; + mutex_lock(&smcreg.mutex); + ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len); + mutex_unlock(&smcreg.mutex); - for (i = 0; i < 4; i++) { - outb(readkey[i], APPLESMC_DATA_PORT); - if (__wait_status(0x04)) - return -EIO; + return ret; +} + +static int applesmc_write_entry(const struct applesmc_entry *entry, + const u8 *buf, u8 len) +{ + int ret; + + if (entry->len != len) + return -EINVAL; + mutex_lock(&smcreg.mutex); + ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len); + mutex_unlock(&smcreg.mutex); + return ret; +} + +static const struct applesmc_entry *applesmc_get_entry_by_index(int index) +{ + struct applesmc_entry *cache = &smcreg.cache[index]; + u8 key[4], info[6]; + __be32 be; + int ret = 0; + + if (cache->valid) + return cache; + + mutex_lock(&smcreg.mutex); + + if (cache->valid) + goto out; + be = cpu_to_be32(index); + ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); + if (ret) + goto out; + ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); + if (ret) + goto out; + + memcpy(cache->key, key, 4); + cache->len = info[0]; + memcpy(cache->type, &info[1], 4); + cache->flags = info[5]; + cache->valid = 1; + +out: + mutex_unlock(&smcreg.mutex); + if (ret) + return ERR_PTR(ret); + return cache; +} + +static int applesmc_get_lower_bound(unsigned int *lo, const char *key) +{ + int begin = 0, end = smcreg.key_count; + const struct applesmc_entry *entry; + + while (begin != end) { + int middle = begin + (end - begin) / 2; + entry = applesmc_get_entry_by_index(middle); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (strcmp(entry->key, key) < 0) + begin = middle + 1; + else + end = middle; } - outb(4, APPLESMC_DATA_PORT); + *lo = begin; + return 0; +} - for (i = 0; i < 4; i++) { - if (__wait_status(0x05)) - return -EIO; - key[i] = inb(APPLESMC_DATA_PORT); +static int applesmc_get_upper_bound(unsigned int *hi, const char *key) +{ + int begin = 0, end = smcreg.key_count; + const struct applesmc_entry *entry; + + while (begin != end) { + int middle = begin + (end - begin) / 2; + entry = applesmc_get_entry_by_index(middle); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (strcmp(key, entry->key) < 0) + end = middle; + else + begin = middle + 1; } - key[4] = 0; + *hi = begin; return 0; } -/* - * applesmc_get_key_type - get key type, and put the result in type (char[6]). - * Returns zero on success or a negative error on failure. Callers must - * hold applesmc_lock. - */ -static int applesmc_get_key_type(char* key, char* type) +static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key) { - int i; + int begin, end; + int ret; - if (send_command(APPLESMC_GET_KEY_TYPE_CMD)) - return -EIO; + ret = applesmc_get_lower_bound(&begin, key); + if (ret) + return ERR_PTR(ret); + ret = applesmc_get_upper_bound(&end, key); + if (ret) + return ERR_PTR(ret); + if (end - begin != 1) + return ERR_PTR(-EINVAL); - for (i = 0; i < 4; i++) { - outb(key[i], APPLESMC_DATA_PORT); - if (__wait_status(0x04)) - return -EIO; - } + return applesmc_get_entry_by_index(begin); +} - outb(6, APPLESMC_DATA_PORT); +static int applesmc_read_key(const char *key, u8 *buffer, u8 len) +{ + const struct applesmc_entry *entry; - for (i = 0; i < 6; i++) { - if (__wait_status(0x05)) - return -EIO; - type[i] = inb(APPLESMC_DATA_PORT); - } - type[5] = 0; + entry = applesmc_get_entry_by_key(key); + if (IS_ERR(entry)) + return PTR_ERR(entry); + + return applesmc_read_entry(entry, buffer, len); +} + +static int applesmc_write_key(const char *key, const u8 *buffer, u8 len) +{ + const struct applesmc_entry *entry; + entry = applesmc_get_entry_by_key(key); + if (IS_ERR(entry)) + return PTR_ERR(entry); + + return applesmc_write_entry(entry, buffer, len); +} + +static int applesmc_has_key(const char *key, bool *value) +{ + const struct applesmc_entry *entry; + + entry = applesmc_get_entry_by_key(key); + if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL) + return PTR_ERR(entry); + + *value = !IS_ERR(entry); return 0; } /* - * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must - * hold applesmc_lock. + * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). */ -static int applesmc_read_motion_sensor(int index, s16* value) +static int applesmc_read_motion_sensor(int index, s16 *value) { u8 buffer[2]; int ret; @@ -444,69 +455,120 @@ static int applesmc_read_motion_sensor(int index, s16* value) } /* - * applesmc_device_init - initialize the accelerometer. Returns zero on success - * and negative error code on failure. Can sleep. + * applesmc_device_init - initialize the accelerometer. Can sleep. */ -static int applesmc_device_init(void) +static void applesmc_device_init(void) { - int total, ret = -ENXIO; + int total; u8 buffer[2]; - if (!applesmc_accelerometer) - return 0; - - mutex_lock(&applesmc_lock); + if (!smcreg.has_accelerometer) + return; for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { - if (debug) - printk(KERN_DEBUG "applesmc try %d\n", total); if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) && - (buffer[0] != 0x00 || buffer[1] != 0x00)) { - if (total == INIT_TIMEOUT_MSECS) { - printk(KERN_DEBUG "applesmc: device has" - " already been initialized" - " (0x%02x, 0x%02x).\n", - buffer[0], buffer[1]); - } else { - printk(KERN_DEBUG "applesmc: device" - " successfully initialized" - " (0x%02x, 0x%02x).\n", - buffer[0], buffer[1]); - } - ret = 0; - goto out; - } + (buffer[0] != 0x00 || buffer[1] != 0x00)) + return; buffer[0] = 0xe0; buffer[1] = 0x00; applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2); msleep(INIT_WAIT_MSECS); } - printk(KERN_WARNING "applesmc: failed to init the device\n"); - -out: - mutex_unlock(&applesmc_lock); - return ret; + pr_warn("failed to init the device\n"); } /* - * applesmc_get_fan_count - get the number of fans. Callers must NOT hold - * applesmc_lock. + * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. */ -static int applesmc_get_fan_count(void) +static int applesmc_init_smcreg_try(void) { + struct applesmc_registers *s = &smcreg; + bool left_light_sensor, right_light_sensor; + u8 tmp[1]; int ret; - u8 buffer[1]; - mutex_lock(&applesmc_lock); + if (s->init_complete) + return 0; - ret = applesmc_read_key(FANS_COUNT, buffer, 1); + ret = read_register_count(&s->key_count); + if (ret) + return ret; + + if (!s->cache) + s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL); + if (!s->cache) + return -ENOMEM; - mutex_unlock(&applesmc_lock); + ret = applesmc_read_key(FANS_COUNT, tmp, 1); if (ret) return ret; - else - return buffer[0]; + s->fan_count = tmp[0]; + + ret = applesmc_get_lower_bound(&s->temp_begin, "T"); + if (ret) + return ret; + ret = applesmc_get_lower_bound(&s->temp_end, "U"); + if (ret) + return ret; + s->temp_count = s->temp_end - s->temp_begin; + + ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); + if (ret) + return ret; + ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor); + if (ret) + return ret; + ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer); + if (ret) + return ret; + ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight); + if (ret) + return ret; + + s->num_light_sensors = left_light_sensor + right_light_sensor; + s->init_complete = true; + + pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n", + s->key_count, s->fan_count, s->temp_count, + s->has_accelerometer, + s->num_light_sensors, + s->has_key_backlight); + + return 0; +} + +/* + * applesmc_init_smcreg - Initialize register cache. + * + * Retries until initialization is successful, or the operation times out. + * + */ +static int applesmc_init_smcreg(void) +{ + int ms, ret; + + for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) { + ret = applesmc_init_smcreg_try(); + if (!ret) { + if (ms) + pr_info("init_smcreg() took %d ms\n", ms); + return 0; + } + msleep(INIT_WAIT_MSECS); + } + + kfree(smcreg.cache); + smcreg.cache = NULL; + + return ret; +} + +static void applesmc_destroy_smcreg(void) +{ + kfree(smcreg.cache); + smcreg.cache = NULL; + smcreg.init_complete = false; } /* Device model stuff */ @@ -514,30 +576,27 @@ static int applesmc_probe(struct platform_device *dev) { int ret; - ret = applesmc_device_init(); + ret = applesmc_init_smcreg(); if (ret) return ret; - printk(KERN_INFO "applesmc: device successfully initialized.\n"); + applesmc_device_init(); + return 0; } /* Synchronize device with memorized backlight state */ static int applesmc_pm_resume(struct device *dev) { - mutex_lock(&applesmc_lock); - if (applesmc_light) + if (smcreg.has_key_backlight) applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); - mutex_unlock(&applesmc_lock); return 0; } /* Reinitialize device on resume from hibernation */ static int applesmc_pm_restore(struct device *dev) { - int ret = applesmc_device_init(); - if (ret) - return ret; + applesmc_device_init(); return applesmc_pm_resume(dev); } @@ -571,20 +630,15 @@ static void applesmc_idev_poll(struct input_polled_dev *dev) struct input_dev *idev = dev->input; s16 x, y; - mutex_lock(&applesmc_lock); - if (applesmc_read_motion_sensor(SENSOR_X, &x)) - goto out; + return; if (applesmc_read_motion_sensor(SENSOR_Y, &y)) - goto out; + return; x = -x; input_report_abs(idev, ABS_X, x - rest_x); input_report_abs(idev, ABS_Y, y - rest_y); input_sync(idev); - -out: - mutex_unlock(&applesmc_lock); } /* Sysfs Files */ @@ -601,8 +655,6 @@ static ssize_t applesmc_position_show(struct device *dev, int ret; s16 x, y, z; - mutex_lock(&applesmc_lock); - ret = applesmc_read_motion_sensor(SENSOR_X, &x); if (ret) goto out; @@ -614,7 +666,6 @@ static ssize_t applesmc_position_show(struct device *dev, goto out; out: - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -624,20 +675,20 @@ out: static ssize_t applesmc_light_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { + const struct applesmc_entry *entry; static int data_length; int ret; u8 left = 0, right = 0; - u8 buffer[10], query[6]; - - mutex_lock(&applesmc_lock); + u8 buffer[10]; if (!data_length) { - ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query); - if (ret) - goto out; - data_length = clamp_val(query[0], 0, 10); - printk(KERN_INFO "applesmc: light sensor data length set to " - "%d\n", data_length); + entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (entry->len > 10) + return -ENXIO; + data_length = entry->len; + pr_info("light sensor data length set to %d\n", data_length); } ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length); @@ -653,7 +704,6 @@ static ssize_t applesmc_light_show(struct device *dev, right = buffer[2]; out: - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -664,36 +714,44 @@ out: static ssize_t applesmc_show_sensor_label(struct device *dev, struct device_attribute *devattr, char *sysfsbuf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - const char *key = - temperature_sensors_sets[applesmc_temperature_set][attr->index]; + int index = smcreg.temp_begin + to_index(devattr); + const struct applesmc_entry *entry; + + entry = applesmc_get_entry_by_index(index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key); + return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); } /* Displays degree Celsius * 1000 */ static ssize_t applesmc_show_temperature(struct device *dev, struct device_attribute *devattr, char *sysfsbuf) { + int index = smcreg.temp_begin + to_index(devattr); + const struct applesmc_entry *entry; int ret; u8 buffer[2]; unsigned int temp; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - const char* key = - temperature_sensors_sets[applesmc_temperature_set][attr->index]; - - mutex_lock(&applesmc_lock); - ret = applesmc_read_key(key, buffer, 2); - temp = buffer[0]*1000; - temp += (buffer[1] >> 6) * 250; - - mutex_unlock(&applesmc_lock); + entry = applesmc_get_entry_by_index(index); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (entry->len > 2) + return -EINVAL; + ret = applesmc_read_entry(entry, buffer, entry->len); if (ret) return ret; - else - return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp); + + if (entry->len == 2) { + temp = buffer[0] * 1000; + temp += (buffer[1] >> 6) * 250; + } else { + temp = buffer[0] * 4000; + } + + return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp); } static ssize_t applesmc_show_fan_speed(struct device *dev, @@ -703,21 +761,12 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, unsigned int speed = 0; char newkey[5]; u8 buffer[2]; - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - - newkey[0] = fan_speed_keys[sensor_attr->nr][0]; - newkey[1] = '0' + sensor_attr->index; - newkey[2] = fan_speed_keys[sensor_attr->nr][2]; - newkey[3] = fan_speed_keys[sensor_attr->nr][3]; - newkey[4] = 0; - mutex_lock(&applesmc_lock); + sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr)); ret = applesmc_read_key(newkey, buffer, 2); speed = ((buffer[0] << 8 | buffer[1]) >> 2); - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -729,30 +778,19 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, const char *sysfsbuf, size_t count) { int ret; - u32 speed; + unsigned long speed; char newkey[5]; u8 buffer[2]; - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - - speed = simple_strtoul(sysfsbuf, NULL, 10); - - if (speed > 0x4000) /* Bigger than a 14-bit value */ - return -EINVAL; - newkey[0] = fan_speed_keys[sensor_attr->nr][0]; - newkey[1] = '0' + sensor_attr->index; - newkey[2] = fan_speed_keys[sensor_attr->nr][2]; - newkey[3] = fan_speed_keys[sensor_attr->nr][3]; - newkey[4] = 0; + if (strict_strtoul(sysfsbuf, 10, &speed) < 0 || speed >= 0x4000) + return -EINVAL; /* Bigger than a 14-bit value */ - mutex_lock(&applesmc_lock); + sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr)); buffer[0] = (speed >> 6) & 0xff; buffer[1] = (speed << 2) & 0xff; ret = applesmc_write_key(newkey, buffer, 2); - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -760,19 +798,15 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, } static ssize_t applesmc_show_fan_manual(struct device *dev, - struct device_attribute *devattr, char *sysfsbuf) + struct device_attribute *attr, char *sysfsbuf) { int ret; u16 manual = 0; u8 buffer[2]; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - - mutex_lock(&applesmc_lock); ret = applesmc_read_key(FANS_MANUAL, buffer, 2); - manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01; + manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01; - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -780,18 +814,16 @@ static ssize_t applesmc_show_fan_manual(struct device *dev, } static ssize_t applesmc_store_fan_manual(struct device *dev, - struct device_attribute *devattr, + struct device_attribute *attr, const char *sysfsbuf, size_t count) { int ret; u8 buffer[2]; - u32 input; + unsigned long input; u16 val; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - - input = simple_strtoul(sysfsbuf, NULL, 10); - mutex_lock(&applesmc_lock); + if (strict_strtoul(sysfsbuf, 10, &input) < 0) + return -EINVAL; ret = applesmc_read_key(FANS_MANUAL, buffer, 2); val = (buffer[0] << 8 | buffer[1]); @@ -799,9 +831,9 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, goto out; if (input) - val = val | (0x01 << attr->index); + val = val | (0x01 << to_index(attr)); else - val = val & ~(0x01 << attr->index); + val = val & ~(0x01 << to_index(attr)); buffer[0] = (val >> 8) & 0xFF; buffer[1] = val & 0xFF; @@ -809,7 +841,6 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, ret = applesmc_write_key(FANS_MANUAL, buffer, 2); out: - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -822,21 +853,12 @@ static ssize_t applesmc_show_fan_position(struct device *dev, int ret; char newkey[5]; u8 buffer[17]; - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - - newkey[0] = FAN_POSITION[0]; - newkey[1] = '0' + sensor_attr->index; - newkey[2] = FAN_POSITION[2]; - newkey[3] = FAN_POSITION[3]; - newkey[4] = 0; - mutex_lock(&applesmc_lock); + sprintf(newkey, FAN_ID_FMT, to_index(attr)); ret = applesmc_read_key(newkey, buffer, 16); buffer[16] = 0; - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -852,18 +874,14 @@ static ssize_t applesmc_calibrate_show(struct device *dev, static ssize_t applesmc_calibrate_store(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count) { - mutex_lock(&applesmc_lock); applesmc_calibrate(); - mutex_unlock(&applesmc_lock); return count; } static void applesmc_backlight_set(struct work_struct *work) { - mutex_lock(&applesmc_lock); applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); - mutex_unlock(&applesmc_lock); } static DECLARE_WORK(backlight_work, &applesmc_backlight_set); @@ -886,13 +904,10 @@ static ssize_t applesmc_key_count_show(struct device *dev, u8 buffer[4]; u32 count; - mutex_lock(&applesmc_lock); - ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4); count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) + ((u32)buffer[2]<<8) + buffer[3]; - mutex_unlock(&applesmc_lock); if (ret) return ret; else @@ -902,113 +917,53 @@ static ssize_t applesmc_key_count_show(struct device *dev, static ssize_t applesmc_key_at_index_read_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - char key[5]; - char info[6]; + const struct applesmc_entry *entry; int ret; - mutex_lock(&applesmc_lock); - - ret = applesmc_get_key_at_index(key_at_index, key); - - if (ret || !key[0]) { - mutex_unlock(&applesmc_lock); - - return -EINVAL; - } - - ret = applesmc_get_key_type(key, info); - - if (ret) { - mutex_unlock(&applesmc_lock); - + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); + ret = applesmc_read_entry(entry, sysfsbuf, entry->len); + if (ret) return ret; - } - - /* - * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than - * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf. - */ - ret = applesmc_read_key(key, sysfsbuf, info[0]); - - mutex_unlock(&applesmc_lock); - if (!ret) { - return info[0]; - } else { - return ret; - } + return entry->len; } static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - char key[5]; - char info[6]; - int ret; - - mutex_lock(&applesmc_lock); - - ret = applesmc_get_key_at_index(key_at_index, key); + const struct applesmc_entry *entry; - if (ret || !key[0]) { - mutex_unlock(&applesmc_lock); + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return -EINVAL; - } - - ret = applesmc_get_key_type(key, info); - - mutex_unlock(&applesmc_lock); - - if (!ret) - return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", info[0]); - else - return ret; + return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len); } static ssize_t applesmc_key_at_index_type_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - char key[5]; - char info[6]; - int ret; - - mutex_lock(&applesmc_lock); - - ret = applesmc_get_key_at_index(key_at_index, key); - - if (ret || !key[0]) { - mutex_unlock(&applesmc_lock); - - return -EINVAL; - } - - ret = applesmc_get_key_type(key, info); + const struct applesmc_entry *entry; - mutex_unlock(&applesmc_lock); + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - if (!ret) - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", info+1); - else - return ret; + return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type); } static ssize_t applesmc_key_at_index_name_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - char key[5]; - int ret; + const struct applesmc_entry *entry; - mutex_lock(&applesmc_lock); + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - ret = applesmc_get_key_at_index(key_at_index, key); - - mutex_unlock(&applesmc_lock); - - if (!ret && key[0]) - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key); - else - return -EINVAL; + return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); } static ssize_t applesmc_key_at_index_show(struct device *dev, @@ -1020,12 +975,13 @@ static ssize_t applesmc_key_at_index_show(struct device *dev, static ssize_t applesmc_key_at_index_store(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count) { - mutex_lock(&applesmc_lock); - - key_at_index = simple_strtoul(sysfsbuf, NULL, 10); + unsigned long newkey; - mutex_unlock(&applesmc_lock); + if (strict_strtoul(sysfsbuf, 10, &newkey) < 0 + || newkey >= smcreg.key_count) + return -EINVAL; + key_at_index = newkey; return count; } @@ -1035,387 +991,102 @@ static struct led_classdev applesmc_backlight = { .brightness_set = applesmc_brightness_set, }; -static DEVICE_ATTR(name, 0444, applesmc_name_show, NULL); - -static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL); -static DEVICE_ATTR(calibrate, 0644, - applesmc_calibrate_show, applesmc_calibrate_store); - -static struct attribute *accelerometer_attributes[] = { - &dev_attr_position.attr, - &dev_attr_calibrate.attr, - NULL -}; - -static const struct attribute_group accelerometer_attributes_group = - { .attrs = accelerometer_attributes }; - -static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL); - -static DEVICE_ATTR(key_count, 0444, applesmc_key_count_show, NULL); -static DEVICE_ATTR(key_at_index, 0644, - applesmc_key_at_index_show, applesmc_key_at_index_store); -static DEVICE_ATTR(key_at_index_name, 0444, - applesmc_key_at_index_name_show, NULL); -static DEVICE_ATTR(key_at_index_type, 0444, - applesmc_key_at_index_type_show, NULL); -static DEVICE_ATTR(key_at_index_data_length, 0444, - applesmc_key_at_index_data_length_show, NULL); -static DEVICE_ATTR(key_at_index_data, 0444, - applesmc_key_at_index_read_show, NULL); - -static struct attribute *key_enumeration_attributes[] = { - &dev_attr_key_count.attr, - &dev_attr_key_at_index.attr, - &dev_attr_key_at_index_name.attr, - &dev_attr_key_at_index_type.attr, - &dev_attr_key_at_index_data_length.attr, - &dev_attr_key_at_index_data.attr, - NULL -}; - -static const struct attribute_group key_enumeration_group = - { .attrs = key_enumeration_attributes }; - -/* - * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries. - * - show actual speed - * - show/store minimum speed - * - show maximum speed - * - show safe speed - * - show/store target speed - * - show/store manual mode - */ -#define sysfs_fan_speeds_offset(offset) \ -static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \ - applesmc_show_fan_speed, NULL, 0, offset-1); \ -\ -static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \ - applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \ -\ -static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \ - applesmc_show_fan_speed, NULL, 2, offset-1); \ -\ -static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \ - applesmc_show_fan_speed, NULL, 3, offset-1); \ -\ -static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \ - applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \ -\ -static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \ - applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \ -\ -static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \ - applesmc_show_fan_position, NULL, offset-1); \ -\ -static struct attribute *fan##offset##_attributes[] = { \ - &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \ - &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \ - &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \ - &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \ - &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \ - &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \ - &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \ - NULL \ +static struct applesmc_node_group info_group[] = { + { "name", applesmc_name_show }, + { "key_count", applesmc_key_count_show }, + { "key_at_index", applesmc_key_at_index_show, applesmc_key_at_index_store }, + { "key_at_index_name", applesmc_key_at_index_name_show }, + { "key_at_index_type", applesmc_key_at_index_type_show }, + { "key_at_index_data_length", applesmc_key_at_index_data_length_show }, + { "key_at_index_data", applesmc_key_at_index_read_show }, + { } }; -/* - * Create the needed functions for each fan using the macro defined above - * (4 fans are supported) - */ -sysfs_fan_speeds_offset(1); -sysfs_fan_speeds_offset(2); -sysfs_fan_speeds_offset(3); -sysfs_fan_speeds_offset(4); - -static const struct attribute_group fan_attribute_groups[] = { - { .attrs = fan1_attributes }, - { .attrs = fan2_attributes }, - { .attrs = fan3_attributes }, - { .attrs = fan4_attributes }, +static struct applesmc_node_group accelerometer_group[] = { + { "position", applesmc_position_show }, + { "calibrate", applesmc_calibrate_show, applesmc_calibrate_store }, + { } }; -/* - * Temperature sensors sysfs entries. - */ -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 7); -static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 8); -static SENSOR_DEVICE_ATTR(temp10_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 9); -static SENSOR_DEVICE_ATTR(temp11_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 10); -static SENSOR_DEVICE_ATTR(temp12_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 11); -static SENSOR_DEVICE_ATTR(temp13_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 12); -static SENSOR_DEVICE_ATTR(temp14_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 13); -static SENSOR_DEVICE_ATTR(temp15_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 14); -static SENSOR_DEVICE_ATTR(temp16_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 15); -static SENSOR_DEVICE_ATTR(temp17_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 16); -static SENSOR_DEVICE_ATTR(temp18_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 17); -static SENSOR_DEVICE_ATTR(temp19_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 18); -static SENSOR_DEVICE_ATTR(temp20_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 19); -static SENSOR_DEVICE_ATTR(temp21_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 20); -static SENSOR_DEVICE_ATTR(temp22_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 21); -static SENSOR_DEVICE_ATTR(temp23_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 22); -static SENSOR_DEVICE_ATTR(temp24_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 23); -static SENSOR_DEVICE_ATTR(temp25_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 24); -static SENSOR_DEVICE_ATTR(temp26_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 25); -static SENSOR_DEVICE_ATTR(temp27_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 26); -static SENSOR_DEVICE_ATTR(temp28_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 27); -static SENSOR_DEVICE_ATTR(temp29_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 28); -static SENSOR_DEVICE_ATTR(temp30_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 29); -static SENSOR_DEVICE_ATTR(temp31_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 30); -static SENSOR_DEVICE_ATTR(temp32_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 31); -static SENSOR_DEVICE_ATTR(temp33_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 32); -static SENSOR_DEVICE_ATTR(temp34_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 33); -static SENSOR_DEVICE_ATTR(temp35_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 34); -static SENSOR_DEVICE_ATTR(temp36_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 35); -static SENSOR_DEVICE_ATTR(temp37_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 36); -static SENSOR_DEVICE_ATTR(temp38_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 37); -static SENSOR_DEVICE_ATTR(temp39_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 38); -static SENSOR_DEVICE_ATTR(temp40_label, S_IRUGO, - applesmc_show_sensor_label, NULL, 39); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - applesmc_show_temperature, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, - applesmc_show_temperature, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, - applesmc_show_temperature, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, - applesmc_show_temperature, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, - applesmc_show_temperature, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, - applesmc_show_temperature, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, - applesmc_show_temperature, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, - applesmc_show_temperature, NULL, 7); -static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, - applesmc_show_temperature, NULL, 8); -static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, - applesmc_show_temperature, NULL, 9); -static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, - applesmc_show_temperature, NULL, 10); -static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, - applesmc_show_temperature, NULL, 11); -static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, - applesmc_show_temperature, NULL, 12); -static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, - applesmc_show_temperature, NULL, 13); -static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, - applesmc_show_temperature, NULL, 14); -static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO, - applesmc_show_temperature, NULL, 15); -static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO, - applesmc_show_temperature, NULL, 16); -static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO, - applesmc_show_temperature, NULL, 17); -static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO, - applesmc_show_temperature, NULL, 18); -static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO, - applesmc_show_temperature, NULL, 19); -static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO, - applesmc_show_temperature, NULL, 20); -static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO, - applesmc_show_temperature, NULL, 21); -static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO, - applesmc_show_temperature, NULL, 22); -static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO, - applesmc_show_temperature, NULL, 23); -static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO, - applesmc_show_temperature, NULL, 24); -static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO, - applesmc_show_temperature, NULL, 25); -static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO, - applesmc_show_temperature, NULL, 26); -static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO, - applesmc_show_temperature, NULL, 27); -static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO, - applesmc_show_temperature, NULL, 28); -static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO, - applesmc_show_temperature, NULL, 29); -static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO, - applesmc_show_temperature, NULL, 30); -static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO, - applesmc_show_temperature, NULL, 31); -static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO, - applesmc_show_temperature, NULL, 32); -static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO, - applesmc_show_temperature, NULL, 33); -static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO, - applesmc_show_temperature, NULL, 34); -static SENSOR_DEVICE_ATTR(temp36_input, S_IRUGO, - applesmc_show_temperature, NULL, 35); -static SENSOR_DEVICE_ATTR(temp37_input, S_IRUGO, - applesmc_show_temperature, NULL, 36); -static SENSOR_DEVICE_ATTR(temp38_input, S_IRUGO, - applesmc_show_temperature, NULL, 37); -static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO, - applesmc_show_temperature, NULL, 38); -static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO, - applesmc_show_temperature, NULL, 39); - -static struct attribute *label_attributes[] = { - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp2_label.dev_attr.attr, - &sensor_dev_attr_temp3_label.dev_attr.attr, - &sensor_dev_attr_temp4_label.dev_attr.attr, - &sensor_dev_attr_temp5_label.dev_attr.attr, - &sensor_dev_attr_temp6_label.dev_attr.attr, - &sensor_dev_attr_temp7_label.dev_attr.attr, - &sensor_dev_attr_temp8_label.dev_attr.attr, - &sensor_dev_attr_temp9_label.dev_attr.attr, - &sensor_dev_attr_temp10_label.dev_attr.attr, - &sensor_dev_attr_temp11_label.dev_attr.attr, - &sensor_dev_attr_temp12_label.dev_attr.attr, - &sensor_dev_attr_temp13_label.dev_attr.attr, - &sensor_dev_attr_temp14_label.dev_attr.attr, - &sensor_dev_attr_temp15_label.dev_attr.attr, - &sensor_dev_attr_temp16_label.dev_attr.attr, - &sensor_dev_attr_temp17_label.dev_attr.attr, - &sensor_dev_attr_temp18_label.dev_attr.attr, - &sensor_dev_attr_temp19_label.dev_attr.attr, - &sensor_dev_attr_temp20_label.dev_attr.attr, - &sensor_dev_attr_temp21_label.dev_attr.attr, - &sensor_dev_attr_temp22_label.dev_attr.attr, - &sensor_dev_attr_temp23_label.dev_attr.attr, - &sensor_dev_attr_temp24_label.dev_attr.attr, - &sensor_dev_attr_temp25_label.dev_attr.attr, - &sensor_dev_attr_temp26_label.dev_attr.attr, - &sensor_dev_attr_temp27_label.dev_attr.attr, - &sensor_dev_attr_temp28_label.dev_attr.attr, - &sensor_dev_attr_temp29_label.dev_attr.attr, - &sensor_dev_attr_temp30_label.dev_attr.attr, - &sensor_dev_attr_temp31_label.dev_attr.attr, - &sensor_dev_attr_temp32_label.dev_attr.attr, - &sensor_dev_attr_temp33_label.dev_attr.attr, - &sensor_dev_attr_temp34_label.dev_attr.attr, - &sensor_dev_attr_temp35_label.dev_attr.attr, - &sensor_dev_attr_temp36_label.dev_attr.attr, - &sensor_dev_attr_temp37_label.dev_attr.attr, - &sensor_dev_attr_temp38_label.dev_attr.attr, - &sensor_dev_attr_temp39_label.dev_attr.attr, - &sensor_dev_attr_temp40_label.dev_attr.attr, - NULL +static struct applesmc_node_group light_sensor_group[] = { + { "light", applesmc_light_show }, + { } }; -static struct attribute *temperature_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp7_input.dev_attr.attr, - &sensor_dev_attr_temp8_input.dev_attr.attr, - &sensor_dev_attr_temp9_input.dev_attr.attr, - &sensor_dev_attr_temp10_input.dev_attr.attr, - &sensor_dev_attr_temp11_input.dev_attr.attr, - &sensor_dev_attr_temp12_input.dev_attr.attr, - &sensor_dev_attr_temp13_input.dev_attr.attr, - &sensor_dev_attr_temp14_input.dev_attr.attr, - &sensor_dev_attr_temp15_input.dev_attr.attr, - &sensor_dev_attr_temp16_input.dev_attr.attr, - &sensor_dev_attr_temp17_input.dev_attr.attr, - &sensor_dev_attr_temp18_input.dev_attr.attr, - &sensor_dev_attr_temp19_input.dev_attr.attr, - &sensor_dev_attr_temp20_input.dev_attr.attr, - &sensor_dev_attr_temp21_input.dev_attr.attr, - &sensor_dev_attr_temp22_input.dev_attr.attr, - &sensor_dev_attr_temp23_input.dev_attr.attr, - &sensor_dev_attr_temp24_input.dev_attr.attr, - &sensor_dev_attr_temp25_input.dev_attr.attr, - &sensor_dev_attr_temp26_input.dev_attr.attr, - &sensor_dev_attr_temp27_input.dev_attr.attr, - &sensor_dev_attr_temp28_input.dev_attr.attr, - &sensor_dev_attr_temp29_input.dev_attr.attr, - &sensor_dev_attr_temp30_input.dev_attr.attr, - &sensor_dev_attr_temp31_input.dev_attr.attr, - &sensor_dev_attr_temp32_input.dev_attr.attr, - &sensor_dev_attr_temp33_input.dev_attr.attr, - &sensor_dev_attr_temp34_input.dev_attr.attr, - &sensor_dev_attr_temp35_input.dev_attr.attr, - &sensor_dev_attr_temp36_input.dev_attr.attr, - &sensor_dev_attr_temp37_input.dev_attr.attr, - &sensor_dev_attr_temp38_input.dev_attr.attr, - &sensor_dev_attr_temp39_input.dev_attr.attr, - &sensor_dev_attr_temp40_input.dev_attr.attr, - NULL +static struct applesmc_node_group fan_group[] = { + { "fan%d_label", applesmc_show_fan_position }, + { "fan%d_input", applesmc_show_fan_speed, NULL, 0 }, + { "fan%d_min", applesmc_show_fan_speed, applesmc_store_fan_speed, 1 }, + { "fan%d_max", applesmc_show_fan_speed, NULL, 2 }, + { "fan%d_safe", applesmc_show_fan_speed, NULL, 3 }, + { "fan%d_output", applesmc_show_fan_speed, applesmc_store_fan_speed, 4 }, + { "fan%d_manual", applesmc_show_fan_manual, applesmc_store_fan_manual }, + { } }; -static const struct attribute_group temperature_attributes_group = - { .attrs = temperature_attributes }; - -static const struct attribute_group label_attributes_group = { - .attrs = label_attributes +static struct applesmc_node_group temp_group[] = { + { "temp%d_label", applesmc_show_sensor_label }, + { "temp%d_input", applesmc_show_temperature }, + { } }; /* Module stuff */ /* - * applesmc_dmi_match - found a match. return one, short-circuiting the hunt. + * applesmc_destroy_nodes - remove files and free associated memory */ -static int applesmc_dmi_match(const struct dmi_system_id *id) +static void applesmc_destroy_nodes(struct applesmc_node_group *groups) { - int i = 0; - struct dmi_match_data* dmi_data = id->driver_data; - printk(KERN_INFO "applesmc: %s detected:\n", id->ident); - applesmc_accelerometer = dmi_data->accelerometer; - printk(KERN_INFO "applesmc: - Model %s accelerometer\n", - applesmc_accelerometer ? "with" : "without"); - applesmc_light = dmi_data->light; - printk(KERN_INFO "applesmc: - Model %s light sensors and backlight\n", - applesmc_light ? "with" : "without"); - - applesmc_temperature_set = dmi_data->temperature_set; - while (temperature_sensors_sets[applesmc_temperature_set][i] != NULL) - i++; - printk(KERN_INFO "applesmc: - Model with %d temperature sensors\n", i); - return 1; + struct applesmc_node_group *grp; + struct applesmc_dev_attr *node; + + for (grp = groups; grp->nodes; grp++) { + for (node = grp->nodes; node->sda.dev_attr.attr.name; node++) + sysfs_remove_file(&pdev->dev.kobj, + &node->sda.dev_attr.attr); + kfree(grp->nodes); + grp->nodes = NULL; + } +} + +/* + * applesmc_create_nodes - create a two-dimensional group of sysfs files + */ +static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) +{ + struct applesmc_node_group *grp; + struct applesmc_dev_attr *node; + struct attribute *attr; + int ret, i; + + for (grp = groups; grp->format; grp++) { + grp->nodes = kcalloc(num + 1, sizeof(*node), GFP_KERNEL); + if (!grp->nodes) { + ret = -ENOMEM; + goto out; + } + for (i = 0; i < num; i++) { + node = &grp->nodes[i]; + sprintf(node->name, grp->format, i + 1); + node->sda.index = (grp->option << 16) | (i & 0xffff); + node->sda.dev_attr.show = grp->show; + node->sda.dev_attr.store = grp->store; + attr = &node->sda.dev_attr.attr; + sysfs_attr_init(attr); + attr->name = node->name; + attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0); + ret = sysfs_create_file(&pdev->dev.kobj, attr); + if (ret) { + attr->name = NULL; + goto out; + } + } + } + + return 0; +out: + applesmc_destroy_nodes(groups); + return ret; } /* Create accelerometer ressources */ @@ -1424,8 +1095,10 @@ static int applesmc_create_accelerometer(void) struct input_dev *idev; int ret; - ret = sysfs_create_group(&pdev->dev.kobj, - &accelerometer_attributes_group); + if (!smcreg.has_accelerometer) + return 0; + + ret = applesmc_create_nodes(accelerometer_group, 1); if (ret) goto out; @@ -1462,184 +1135,96 @@ out_idev: input_free_polled_device(applesmc_idev); out_sysfs: - sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); + applesmc_destroy_nodes(accelerometer_group); out: - printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret); + pr_warn("driver init failed (ret=%d)!\n", ret); return ret; } /* Release all ressources used by the accelerometer */ static void applesmc_release_accelerometer(void) { + if (!smcreg.has_accelerometer) + return; input_unregister_polled_device(applesmc_idev); input_free_polled_device(applesmc_idev); - sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); + applesmc_destroy_nodes(accelerometer_group); } -static __initdata struct dmi_match_data applesmc_dmi_data[] = { -/* MacBook Pro: accelerometer, backlight and temperature set 0 */ - { .accelerometer = 1, .light = 1, .temperature_set = 0 }, -/* MacBook2: accelerometer and temperature set 1 */ - { .accelerometer = 1, .light = 0, .temperature_set = 1 }, -/* MacBook: accelerometer and temperature set 2 */ - { .accelerometer = 1, .light = 0, .temperature_set = 2 }, -/* MacMini: temperature set 3 */ - { .accelerometer = 0, .light = 0, .temperature_set = 3 }, -/* MacPro: temperature set 4 */ - { .accelerometer = 0, .light = 0, .temperature_set = 4 }, -/* iMac: temperature set 5 */ - { .accelerometer = 0, .light = 0, .temperature_set = 5 }, -/* MacBook3, MacBook4: accelerometer and temperature set 6 */ - { .accelerometer = 1, .light = 0, .temperature_set = 6 }, -/* MacBook Air: accelerometer, backlight and temperature set 7 */ - { .accelerometer = 1, .light = 1, .temperature_set = 7 }, -/* MacBook Pro 4: accelerometer, backlight and temperature set 8 */ - { .accelerometer = 1, .light = 1, .temperature_set = 8 }, -/* MacBook Pro 3: accelerometer, backlight and temperature set 9 */ - { .accelerometer = 1, .light = 1, .temperature_set = 9 }, -/* iMac 5: light sensor only, temperature set 10 */ - { .accelerometer = 0, .light = 0, .temperature_set = 10 }, -/* MacBook 5: accelerometer, backlight and temperature set 11 */ - { .accelerometer = 1, .light = 1, .temperature_set = 11 }, -/* MacBook Pro 5: accelerometer, backlight and temperature set 12 */ - { .accelerometer = 1, .light = 1, .temperature_set = 12 }, -/* iMac 8: light sensor only, temperature set 13 */ - { .accelerometer = 0, .light = 0, .temperature_set = 13 }, -/* iMac 6: light sensor only, temperature set 14 */ - { .accelerometer = 0, .light = 0, .temperature_set = 14 }, -/* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */ - { .accelerometer = 1, .light = 1, .temperature_set = 15 }, -/* MacPro3,1: temperature set 16 */ - { .accelerometer = 0, .light = 0, .temperature_set = 16 }, -/* iMac 9,1: light sensor only, temperature set 17 */ - { .accelerometer = 0, .light = 0, .temperature_set = 17 }, -/* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */ - { .accelerometer = 1, .light = 1, .temperature_set = 18 }, -/* MacBook Pro 5,3: accelerometer, backlight and temperature set 19 */ - { .accelerometer = 1, .light = 1, .temperature_set = 19 }, -/* MacBook Pro 5,4: accelerometer, backlight and temperature set 20 */ - { .accelerometer = 1, .light = 1, .temperature_set = 20 }, -/* MacBook Pro 6,2: accelerometer, backlight and temperature set 21 */ - { .accelerometer = 1, .light = 1, .temperature_set = 21 }, -/* MacBook Pro 7,1: accelerometer, backlight and temperature set 22 */ - { .accelerometer = 1, .light = 1, .temperature_set = 22 }, -}; +static int applesmc_create_light_sensor(void) +{ + if (!smcreg.num_light_sensors) + return 0; + return applesmc_create_nodes(light_sensor_group, 1); +} + +static void applesmc_release_light_sensor(void) +{ + if (!smcreg.num_light_sensors) + return; + applesmc_destroy_nodes(light_sensor_group); +} + +static int applesmc_create_key_backlight(void) +{ + if (!smcreg.has_key_backlight) + return 0; + applesmc_led_wq = create_singlethread_workqueue("applesmc-led"); + if (!applesmc_led_wq) + return -ENOMEM; + return led_classdev_register(&pdev->dev, &applesmc_backlight); +} + +static void applesmc_release_key_backlight(void) +{ + if (!smcreg.has_key_backlight) + return; + led_classdev_unregister(&applesmc_backlight); + destroy_workqueue(applesmc_led_wq); +} + +static int applesmc_dmi_match(const struct dmi_system_id *id) +{ + return 1; +} /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". * So we need to put "Apple MacBook Pro" before "Apple MacBook". */ static __initdata struct dmi_system_id applesmc_whitelist[] = { - { applesmc_dmi_match, "Apple MacBook Air 2", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") }, - &applesmc_dmi_data[15]}, { applesmc_dmi_match, "Apple MacBook Air", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, - &applesmc_dmi_data[7]}, - { applesmc_dmi_match, "Apple MacBook Pro 7", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro7") }, - &applesmc_dmi_data[22]}, - { applesmc_dmi_match, "Apple MacBook Pro 5,4", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4") }, - &applesmc_dmi_data[20]}, - { applesmc_dmi_match, "Apple MacBook Pro 5,3", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3") }, - &applesmc_dmi_data[19]}, - { applesmc_dmi_match, "Apple MacBook Pro 6", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6") }, - &applesmc_dmi_data[21]}, - { applesmc_dmi_match, "Apple MacBook Pro 5", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") }, - &applesmc_dmi_data[12]}, - { applesmc_dmi_match, "Apple MacBook Pro 4", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") }, - &applesmc_dmi_data[8]}, - { applesmc_dmi_match, "Apple MacBook Pro 3", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") }, - &applesmc_dmi_data[9]}, - { applesmc_dmi_match, "Apple MacBook Pro 2,2", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2") }, - &applesmc_dmi_data[18]}, + }, { applesmc_dmi_match, "Apple MacBook Pro", { - DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), - DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") }, - &applesmc_dmi_data[0]}, - { applesmc_dmi_match, "Apple MacBook (v2)", { - DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), - DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") }, - &applesmc_dmi_data[1]}, - { applesmc_dmi_match, "Apple MacBook (v3)", { - DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), - DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, - &applesmc_dmi_data[6]}, - { applesmc_dmi_match, "Apple MacBook 4", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") }, - &applesmc_dmi_data[6]}, - { applesmc_dmi_match, "Apple MacBook 5", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, - &applesmc_dmi_data[11]}, + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro") }, + }, { applesmc_dmi_match, "Apple MacBook", { - DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), - DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, - &applesmc_dmi_data[2]}, + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") }, + }, { applesmc_dmi_match, "Apple Macmini", { - DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), - DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") }, - &applesmc_dmi_data[3]}, - { applesmc_dmi_match, "Apple MacPro2", { - DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), - DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, - &applesmc_dmi_data[4]}, - { applesmc_dmi_match, "Apple MacPro3", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacPro3") }, - &applesmc_dmi_data[16]}, + DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") }, + }, { applesmc_dmi_match, "Apple MacPro", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, - &applesmc_dmi_data[4]}, - { applesmc_dmi_match, "Apple iMac 9,1", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1") }, - &applesmc_dmi_data[17]}, - { applesmc_dmi_match, "Apple iMac 8", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, - &applesmc_dmi_data[13]}, - { applesmc_dmi_match, "Apple iMac 6", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") }, - &applesmc_dmi_data[14]}, - { applesmc_dmi_match, "Apple iMac 5", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") }, - &applesmc_dmi_data[10]}, + }, { applesmc_dmi_match, "Apple iMac", { - DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), - DMI_MATCH(DMI_PRODUCT_NAME,"iMac") }, - &applesmc_dmi_data[5]}, + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac") }, + }, { .ident = NULL } }; static int __init applesmc_init(void) { int ret; - int count; - int i; if (!dmi_check_system(applesmc_whitelist)) { - printk(KERN_WARNING "applesmc: supported laptop not found!\n"); + pr_warn("supported laptop not found!\n"); ret = -ENODEV; goto out; } @@ -1661,83 +1246,34 @@ static int __init applesmc_init(void) goto out_driver; } - ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr); + /* create register cache */ + ret = applesmc_init_smcreg(); if (ret) goto out_device; - /* Create key enumeration sysfs files */ - ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group); + ret = applesmc_create_nodes(info_group, 1); if (ret) - goto out_name; - - /* create fan files */ - count = applesmc_get_fan_count(); - if (count < 0) - printk(KERN_ERR "applesmc: Cannot get the number of fans.\n"); - else - printk(KERN_INFO "applesmc: %d fans found.\n", count); + goto out_smcreg; - if (count > 4) { - count = 4; - printk(KERN_WARNING "applesmc: More than 4 fans found," - " but at most 4 fans are supported" - " by the driver.\n"); - } - - while (fans_handled < count) { - ret = sysfs_create_group(&pdev->dev.kobj, - &fan_attribute_groups[fans_handled]); - if (ret) - goto out_fans; - fans_handled++; - } - - for (i = 0; - temperature_sensors_sets[applesmc_temperature_set][i] != NULL; - i++) { - if (temperature_attributes[i] == NULL || - label_attributes[i] == NULL) { - printk(KERN_ERR "applesmc: More temperature sensors " - "in temperature_sensors_sets (at least %i)" - "than available sysfs files in " - "temperature_attributes (%i), please report " - "this bug.\n", i, i-1); - goto out_temperature; - } - ret = sysfs_create_file(&pdev->dev.kobj, - temperature_attributes[i]); - if (ret) - goto out_temperature; - ret = sysfs_create_file(&pdev->dev.kobj, - label_attributes[i]); - if (ret) - goto out_temperature; - } + ret = applesmc_create_nodes(fan_group, smcreg.fan_count); + if (ret) + goto out_info; - if (applesmc_accelerometer) { - ret = applesmc_create_accelerometer(); - if (ret) - goto out_temperature; - } + ret = applesmc_create_nodes(temp_group, smcreg.temp_count); + if (ret) + goto out_fans; - if (applesmc_light) { - /* Add light sensor file */ - ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_light.attr); - if (ret) - goto out_accelerometer; + ret = applesmc_create_accelerometer(); + if (ret) + goto out_temperature; - /* Create the workqueue */ - applesmc_led_wq = create_singlethread_workqueue("applesmc-led"); - if (!applesmc_led_wq) { - ret = -ENOMEM; - goto out_light_sysfs; - } + ret = applesmc_create_light_sensor(); + if (ret) + goto out_accelerometer; - /* register as a led device */ - ret = led_classdev_register(&pdev->dev, &applesmc_backlight); - if (ret < 0) - goto out_light_wq; - } + ret = applesmc_create_key_backlight(); + if (ret) + goto out_light_sysfs; hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(hwmon_dev)) { @@ -1745,32 +1281,22 @@ static int __init applesmc_init(void) goto out_light_ledclass; } - printk(KERN_INFO "applesmc: driver successfully loaded.\n"); - return 0; out_light_ledclass: - if (applesmc_light) - led_classdev_unregister(&applesmc_backlight); -out_light_wq: - if (applesmc_light) - destroy_workqueue(applesmc_led_wq); + applesmc_release_key_backlight(); out_light_sysfs: - if (applesmc_light) - sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr); + applesmc_release_light_sensor(); out_accelerometer: - if (applesmc_accelerometer) - applesmc_release_accelerometer(); + applesmc_release_accelerometer(); out_temperature: - sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group); - sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); + applesmc_destroy_nodes(temp_group); out_fans: - while (fans_handled) - sysfs_remove_group(&pdev->dev.kobj, - &fan_attribute_groups[--fans_handled]); - sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); -out_name: - sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); + applesmc_destroy_nodes(fan_group); +out_info: + applesmc_destroy_nodes(info_group); +out_smcreg: + applesmc_destroy_smcreg(); out_device: platform_device_unregister(pdev); out_driver: @@ -1778,32 +1304,23 @@ out_driver: out_region: release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); out: - printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret); + pr_warn("driver init failed (ret=%d)!\n", ret); return ret; } static void __exit applesmc_exit(void) { hwmon_device_unregister(hwmon_dev); - if (applesmc_light) { - led_classdev_unregister(&applesmc_backlight); - destroy_workqueue(applesmc_led_wq); - sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr); - } - if (applesmc_accelerometer) - applesmc_release_accelerometer(); - sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group); - sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); - while (fans_handled) - sysfs_remove_group(&pdev->dev.kobj, - &fan_attribute_groups[--fans_handled]); - sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); - sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); + applesmc_release_key_backlight(); + applesmc_release_light_sensor(); + applesmc_release_accelerometer(); + applesmc_destroy_nodes(temp_group); + applesmc_destroy_nodes(fan_group); + applesmc_destroy_nodes(info_group); + applesmc_destroy_smcreg(); platform_device_unregister(pdev); platform_driver_unregister(&applesmc_driver); release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); - - printk(KERN_INFO "applesmc: driver unloaded.\n"); } module_init(applesmc_init); diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 7dada559b3a1..c02a052d3085 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -36,6 +36,8 @@ asb100 7 3 1 4 0x31 0x0694 yes no */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> @@ -701,8 +703,7 @@ static int asb100_detect(struct i2c_client *client, int val1, val2; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - pr_debug("asb100.o: detect failed, " - "smbus byte data not supported!\n"); + pr_debug("detect failed, smbus byte data not supported!\n"); return -ENODEV; } @@ -715,7 +716,7 @@ static int asb100_detect(struct i2c_client *client, (((!(val1 & 0x80)) && (val2 != 0x94)) || /* Check for ASB100 ID (high byte ) */ ((val1 & 0x80) && (val2 != 0x06)))) { - pr_debug("asb100: detect failed, bad chip id 0x%02x!\n", val2); + pr_debug("detect failed, bad chip id 0x%02x!\n", val2); return -ENODEV; } @@ -744,7 +745,7 @@ static int asb100_probe(struct i2c_client *client, data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL); if (!data) { - pr_debug("asb100.o: probe failed, kzalloc failed!\n"); + pr_debug("probe failed, kzalloc failed!\n"); err = -ENOMEM; goto ERROR0; } diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 23b8555215d2..b5e892017e0c 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -5,12 +5,15 @@ * See COPYING in the top level directory of the kernel tree. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/debugfs.h> #include <linux/kernel.h> #include <linux/hwmon.h> #include <linux/list.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/dmi.h> #include <acpi/acpi.h> #include <acpi/acpixf.h> @@ -20,6 +23,21 @@ #define ATK_HID "ATK0110" +static bool new_if; +module_param(new_if, bool, 0); +MODULE_PARM_DESC(new_if, "Override detection heuristic and force the use of the new ATK0110 interface"); + +static const struct dmi_system_id __initconst atk_force_new_if[] = { + { + /* Old interface has broken MCH temp monitoring */ + .ident = "Asus Sabertooth X58", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58") + } + }, + { } +}; + /* Minimum time between readings, enforced in order to avoid * hogging the CPU. */ @@ -1300,7 +1318,9 @@ static int atk_probe_if(struct atk_data *data) * analysis of multiple DSDTs indicates that when both interfaces * are present the new one (GGRP/GITM) is not functional. */ - if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle) + if (new_if) + dev_info(dev, "Overriding interface detection\n"); + if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle && !new_if) data->old_interface = true; else if (data->enumerate_handle && data->read_handle && data->write_handle) @@ -1414,14 +1434,16 @@ static int __init atk0110_init(void) /* Make sure it's safe to access the device through ACPI */ if (!acpi_resources_are_enforced()) { - pr_err("atk: Resources not safely usable due to " - "acpi_enforce_resources kernel parameter\n"); + pr_err("Resources not safely usable due to acpi_enforce_resources kernel parameter\n"); return -EBUSY; } + if (dmi_check_system(atk_force_new_if)) + new_if = true; + ret = acpi_bus_register_driver(&atk_driver); if (ret) - pr_info("atk: acpi_bus_register_driver failed: %d\n", ret); + pr_info("acpi_bus_register_driver failed: %d\n", ret); return ret; } diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 42de98d73ff5..194ca0aa8b0c 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -20,6 +20,8 @@ * 02110-1301 USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -445,8 +447,8 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) * without thermal sensors will be filtered out. */ if (!cpu_has(c, X86_FEATURE_DTS)) { - printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" - " has no thermal sensor.\n", c->x86_model); + pr_info("CPU (model=0x%x) has no thermal sensor\n", + c->x86_model); return 0; } @@ -466,7 +468,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) pdev = platform_device_alloc(DRVNAME, cpu); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } @@ -478,8 +480,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_free; } diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 980c17d5eeae..d9c592713919 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -25,6 +25,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -75,12 +77,14 @@ enum chips { dme1737, sch5027, sch311x, sch5127 }; * in4 +12V * in5 VTR (+3.3V stby) * in6 Vbat + * in7 Vtrip (sch5127 only) * * --------------------------------------------------------------------- */ -/* Voltages (in) numbered 0-6 (ix) */ -#define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) \ - : 0x94 + (ix)) +/* Voltages (in) numbered 0-7 (ix) */ +#define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) : \ + (ix) < 7 ? 0x94 + (ix) : \ + 0x1f) #define DME1737_REG_IN_MIN(ix) ((ix) < 5 ? 0x44 + (ix) * 2 \ : 0x91 + (ix) * 2) #define DME1737_REG_IN_MAX(ix) ((ix) < 5 ? 0x45 + (ix) * 2 \ @@ -99,10 +103,11 @@ enum chips { dme1737, sch5027, sch311x, sch5127 }; * IN_TEMP_LSB(1) = [temp3, temp1] * IN_TEMP_LSB(2) = [in4, temp2] * IN_TEMP_LSB(3) = [in3, in0] - * IN_TEMP_LSB(4) = [in2, in1] */ + * IN_TEMP_LSB(4) = [in2, in1] + * IN_TEMP_LSB(5) = [res, in7] */ #define DME1737_REG_IN_TEMP_LSB(ix) (0x84 + (ix)) -static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0}; -static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4}; +static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0, 5}; +static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4, 4}; static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1}; static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; @@ -143,7 +148,7 @@ static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; #define DME1737_REG_ALARM1 0x41 #define DME1737_REG_ALARM2 0x42 #define DME1737_REG_ALARM3 0x83 -static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17}; +static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17, 18}; static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6}; static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; @@ -188,6 +193,7 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; #define HAS_PWM_MIN (1 << 4) /* bit 4 */ #define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */ #define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */ +#define HAS_IN7 (1 << 17) /* bit 17 */ /* --------------------------------------------------------------------- * Data structures and manipulation thereof @@ -211,9 +217,9 @@ struct dme1737_data { u32 has_features; /* Register values */ - u16 in[7]; - u8 in_min[7]; - u8 in_max[7]; + u16 in[8]; + u8 in_min[8]; + u8 in_max[8]; s16 temp[3]; s8 temp_min[3]; s8 temp_max[3]; @@ -245,7 +251,7 @@ static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300, static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, 3300}; static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300, - 3300}; + 3300, 1500}; #define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ (type) == sch5127 ? IN_NOMINAL_SCH5127 : \ @@ -578,7 +584,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) { struct dme1737_data *data = dev_get_drvdata(dev); int ix; - u8 lsb[5]; + u8 lsb[6]; mutex_lock(&data->update_lock); @@ -601,6 +607,9 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) /* Voltage inputs are stored as 16 bit values even * though they have only 12 bits resolution. This is * to make it consistent with the temp inputs. */ + if (ix == 7 && !(data->has_features & HAS_IN7)) { + continue; + } data->in[ix] = dme1737_read(data, DME1737_REG_IN(ix)) << 8; data->in_min[ix] = dme1737_read(data, @@ -633,10 +642,16 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) * which the registers are read (MSB first, then LSB) is * important! */ for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) { + if (ix == 5 && !(data->has_features & HAS_IN7)) { + continue; + } lsb[ix] = dme1737_read(data, DME1737_REG_IN_TEMP_LSB(ix)); } for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { + if (ix == 7 && !(data->has_features & HAS_IN7)) { + continue; + } data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] << DME1737_REG_IN_LSB_SHL[ix]) & 0xf0; } @@ -760,7 +775,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) /* --------------------------------------------------------------------- * Voltage sysfs attributes - * ix = [0-5] + * ix = [0-7] * --------------------------------------------------------------------- */ #define SYS_IN_INPUT 0 @@ -1437,7 +1452,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr, * Sysfs device attribute defines and structs * --------------------------------------------------------------------- */ -/* Voltages 0-6 */ +/* Voltages 0-7 */ #define SENSOR_DEVICE_ATTR_IN(ix) \ static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \ @@ -1456,6 +1471,7 @@ SENSOR_DEVICE_ATTR_IN(3); SENSOR_DEVICE_ATTR_IN(4); SENSOR_DEVICE_ATTR_IN(5); SENSOR_DEVICE_ATTR_IN(6); +SENSOR_DEVICE_ATTR_IN(7); /* Temperatures 1-3 */ @@ -1574,7 +1590,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); /* for ISA devices */ * created unconditionally. The attributes that need modification of their * permissions are created read-only and write permissions are added or removed * on the fly when required */ -static struct attribute *dme1737_attr[] ={ +static struct attribute *dme1737_attr[] = { /* Voltages */ &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, @@ -1679,7 +1695,7 @@ static const struct attribute_group dme1737_zone3_group = { }; -/* The following struct holds temp zone hysteresis related attributes, which +/* The following struct holds temp zone hysteresis related attributes, which * are not available in all chips. The following chips support them: * DME1737, SCH311x */ static struct attribute *dme1737_zone_hyst_attr[] = { @@ -1693,6 +1709,21 @@ static const struct attribute_group dme1737_zone_hyst_group = { .attrs = dme1737_zone_hyst_attr, }; +/* The following struct holds voltage in7 related attributes, which + * are not available in all chips. The following chips support them: + * SCH5127 */ +static struct attribute *dme1737_in7_attr[] = { + &sensor_dev_attr_in7_input.dev_attr.attr, + &sensor_dev_attr_in7_min.dev_attr.attr, + &sensor_dev_attr_in7_max.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group dme1737_in7_group = { + .attrs = dme1737_in7_attr, +}; + /* The following structs hold the PWM attributes, some of which are optional. * Their creation depends on the chip configuration which is determined during * module load. */ @@ -1984,6 +2015,9 @@ static void dme1737_remove_files(struct device *dev) if (data->has_features & HAS_ZONE_HYST) { sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group); } + if (data->has_features & HAS_IN7) { + sysfs_remove_group(&dev->kobj, &dme1737_in7_group); + } sysfs_remove_group(&dev->kobj, &dme1737_group); if (!data->client) { @@ -1997,43 +2031,58 @@ static int dme1737_create_files(struct device *dev) int err, ix; /* Create a name attribute for ISA devices */ - if (!data->client && - (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) { - goto exit; + if (!data->client) { + err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr); + if (err) { + goto exit; + } } /* Create standard sysfs attributes */ - if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) { + err = sysfs_create_group(&dev->kobj, &dme1737_group); + if (err) { goto exit_remove; } /* Create chip-dependent sysfs attributes */ - if ((data->has_features & HAS_TEMP_OFFSET) && - (err = sysfs_create_group(&dev->kobj, - &dme1737_temp_offset_group))) { - goto exit_remove; + if (data->has_features & HAS_TEMP_OFFSET) { + err = sysfs_create_group(&dev->kobj, + &dme1737_temp_offset_group); + if (err) { + goto exit_remove; + } } - if ((data->has_features & HAS_VID) && - (err = sysfs_create_group(&dev->kobj, - &dme1737_vid_group))) { - goto exit_remove; + if (data->has_features & HAS_VID) { + err = sysfs_create_group(&dev->kobj, &dme1737_vid_group); + if (err) { + goto exit_remove; + } } - if ((data->has_features & HAS_ZONE3) && - (err = sysfs_create_group(&dev->kobj, - &dme1737_zone3_group))) { - goto exit_remove; + if (data->has_features & HAS_ZONE3) { + err = sysfs_create_group(&dev->kobj, &dme1737_zone3_group); + if (err) { + goto exit_remove; + } } - if ((data->has_features & HAS_ZONE_HYST) && - (err = sysfs_create_group(&dev->kobj, - &dme1737_zone_hyst_group))) { - goto exit_remove; + if (data->has_features & HAS_ZONE_HYST) { + err = sysfs_create_group(&dev->kobj, &dme1737_zone_hyst_group); + if (err) { + goto exit_remove; + } + } + if (data->has_features & HAS_IN7) { + err = sysfs_create_group(&dev->kobj, &dme1737_in7_group); + if (err) { + goto exit_remove; + } } /* Create fan sysfs attributes */ for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { if (data->has_features & HAS_FAN(ix)) { - if ((err = sysfs_create_group(&dev->kobj, - &dme1737_fan_group[ix]))) { + err = sysfs_create_group(&dev->kobj, + &dme1737_fan_group[ix]); + if (err) { goto exit_remove; } } @@ -2042,14 +2091,17 @@ static int dme1737_create_files(struct device *dev) /* Create PWM sysfs attributes */ for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { if (data->has_features & HAS_PWM(ix)) { - if ((err = sysfs_create_group(&dev->kobj, - &dme1737_pwm_group[ix]))) { + err = sysfs_create_group(&dev->kobj, + &dme1737_pwm_group[ix]); + if (err) { goto exit_remove; } - if ((data->has_features & HAS_PWM_MIN) && ix < 3 && - (err = sysfs_create_file(&dev->kobj, - dme1737_auto_pwm_min_attr[ix]))) { - goto exit_remove; + if ((data->has_features & HAS_PWM_MIN) && (ix < 3)) { + err = sysfs_create_file(&dev->kobj, + dme1737_auto_pwm_min_attr[ix]); + if (err) { + goto exit_remove; + } } } } @@ -2186,7 +2238,7 @@ static int dme1737_init_device(struct device *dev) data->has_features |= HAS_ZONE3; break; case sch5127: - data->has_features |= HAS_FAN(2) | HAS_PWM(2); + data->has_features |= HAS_FAN(2) | HAS_PWM(2) | HAS_IN7; break; default: break; @@ -2279,8 +2331,9 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) dme1737_sio_outb(sio_cip, 0x07, 0x0a); /* Get the base address of the runtime registers */ - if (!(addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | - dme1737_sio_inb(sio_cip, 0x61))) { + addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | + dme1737_sio_inb(sio_cip, 0x61); + if (!addr) { err = -ENODEV; goto exit; } @@ -2361,13 +2414,15 @@ static int dme1737_i2c_probe(struct i2c_client *client, mutex_init(&data->update_lock); /* Initialize the DME1737 chip */ - if ((err = dme1737_init_device(dev))) { + err = dme1737_init_device(dev); + if (err) { dev_err(dev, "Failed to initialize device.\n"); goto exit_kfree; } /* Create sysfs files */ - if ((err = dme1737_create_files(dev))) { + err = dme1737_create_files(dev); + if (err) { dev_err(dev, "Failed to create sysfs files.\n"); goto exit_kfree; } @@ -2444,9 +2499,10 @@ static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr) dme1737_sio_outb(sio_cip, 0x07, 0x0a); /* Get the base address of the runtime registers */ - if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | - dme1737_sio_inb(sio_cip, 0x61))) { - printk(KERN_ERR "dme1737: Base address not set.\n"); + base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | + dme1737_sio_inb(sio_cip, 0x61); + if (!base_addr) { + pr_err("Base address not set\n"); err = -ENODEV; goto exit; } @@ -2474,21 +2530,22 @@ static int __init dme1737_isa_device_add(unsigned short addr) if (err) goto exit; - if (!(pdev = platform_device_alloc("dme1737", addr))) { - printk(KERN_ERR "dme1737: Failed to allocate device.\n"); + pdev = platform_device_alloc("dme1737", addr); + if (!pdev) { + pr_err("Failed to allocate device\n"); err = -ENOMEM; goto exit; } - if ((err = platform_device_add_resources(pdev, &res, 1))) { - printk(KERN_ERR "dme1737: Failed to add device resource " - "(err = %d).\n", err); + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + pr_err("Failed to add device resource (err = %d)\n", err); goto exit_device_put; } - if ((err = platform_device_add(pdev))) { - printk(KERN_ERR "dme1737: Failed to add device (err = %d).\n", - err); + err = platform_device_add(pdev); + if (err) { + pr_err("Failed to add device (err = %d)\n", err); goto exit_device_put; } @@ -2514,11 +2571,12 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", (unsigned short)res->start, (unsigned short)res->start + DME1737_EXTENT - 1); - err = -EBUSY; - goto exit; - } + err = -EBUSY; + goto exit; + } - if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) { + data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL); + if (!data) { err = -ENOMEM; goto exit_release_region; } @@ -2565,13 +2623,15 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) data->type == sch5127 ? "SCH5127" : "SCH311x", data->addr); /* Initialize the chip */ - if ((err = dme1737_init_device(dev))) { + err = dme1737_init_device(dev); + if (err) { dev_err(dev, "Failed to initialize device.\n"); goto exit_kfree; } /* Create sysfs files */ - if ((err = dme1737_create_files(dev))) { + err = dme1737_create_files(dev); + if (err) { dev_err(dev, "Failed to create sysfs files.\n"); goto exit_kfree; } @@ -2628,7 +2688,8 @@ static int __init dme1737_init(void) int err; unsigned short addr; - if ((err = i2c_add_driver(&dme1737_i2c_driver))) { + err = i2c_add_driver(&dme1737_i2c_driver); + if (err) { goto exit; } @@ -2641,12 +2702,14 @@ static int __init dme1737_init(void) return 0; } - if ((err = platform_driver_register(&dme1737_isa_driver))) { + err = platform_driver_register(&dme1737_isa_driver); + if (err) { goto exit_del_i2c_driver; } /* Sets global pdev as a side effect */ - if ((err = dme1737_isa_device_add(addr))) { + err = dme1737_isa_device_add(addr); + if (err) { goto exit_del_isa_driver; } diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c new file mode 100644 index 000000000000..257957c69d92 --- /dev/null +++ b/drivers/hwmon/ds620.c @@ -0,0 +1,337 @@ +/* + * ds620.c - Support for temperature sensor and thermostat DS620 + * + * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> + * + * based on ds1621.c by Christian W. Zuckschwerdt <zany@triq.net> + * + * This program 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 program 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 program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/sysfs.h> +#include <linux/i2c/ds620.h> + +/* + * Many DS620 constants specified below + * 15 14 13 12 11 10 09 08 + * |Done|NVB |THF |TLF |R1 |R0 |AUTOC|1SHOT| + * + * 07 06 05 04 03 02 01 00 + * |PO2 |PO1 |A2 |A1 |A0 | | | | + */ +#define DS620_REG_CONFIG_DONE 0x8000 +#define DS620_REG_CONFIG_NVB 0x4000 +#define DS620_REG_CONFIG_THF 0x2000 +#define DS620_REG_CONFIG_TLF 0x1000 +#define DS620_REG_CONFIG_R1 0x0800 +#define DS620_REG_CONFIG_R0 0x0400 +#define DS620_REG_CONFIG_AUTOC 0x0200 +#define DS620_REG_CONFIG_1SHOT 0x0100 +#define DS620_REG_CONFIG_PO2 0x0080 +#define DS620_REG_CONFIG_PO1 0x0040 +#define DS620_REG_CONFIG_A2 0x0020 +#define DS620_REG_CONFIG_A1 0x0010 +#define DS620_REG_CONFIG_A0 0x0008 + +/* The DS620 registers */ +static const u8 DS620_REG_TEMP[3] = { + 0xAA, /* input, word, RO */ + 0xA2, /* min, word, RW */ + 0xA0, /* max, word, RW */ +}; + +#define DS620_REG_CONF 0xAC /* word, RW */ +#define DS620_COM_START 0x51 /* no data */ +#define DS620_COM_STOP 0x22 /* no data */ + +/* Each client has this additional data */ +struct ds620_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + u16 temp[3]; /* Register values, word */ +}; + +/* + * Temperature registers are word-sized. + * DS620 uses a high-byte first convention, which is exactly opposite to + * the SMBus standard. + */ +static int ds620_read_temp(struct i2c_client *client, u8 reg) +{ + int ret; + + ret = i2c_smbus_read_word_data(client, reg); + if (ret < 0) + return ret; + return swab16(ret); +} + +static int ds620_write_temp(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, swab16(value)); +} + +static void ds620_init_client(struct i2c_client *client) +{ + struct ds620_platform_data *ds620_info = client->dev.platform_data; + u16 conf, new_conf; + + new_conf = conf = + swab16(i2c_smbus_read_word_data(client, DS620_REG_CONF)); + + /* switch to continuous conversion mode */ + new_conf &= ~DS620_REG_CONFIG_1SHOT; + /* already high at power-on, but don't trust the BIOS! */ + new_conf |= DS620_REG_CONFIG_PO2; + /* thermostat mode according to platform data */ + if (ds620_info && ds620_info->pomode == 1) + new_conf &= ~DS620_REG_CONFIG_PO1; /* PO_LOW */ + else if (ds620_info && ds620_info->pomode == 2) + new_conf |= DS620_REG_CONFIG_PO1; /* PO_HIGH */ + else + new_conf &= ~DS620_REG_CONFIG_PO2; /* always low */ + /* with highest precision */ + new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0; + + if (conf != new_conf) + i2c_smbus_write_word_data(client, DS620_REG_CONF, + swab16(new_conf)); + + /* start conversion */ + i2c_smbus_write_byte(client, DS620_COM_START); +} + +static struct ds620_data *ds620_update_client(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds620_data *data = i2c_get_clientdata(client); + struct ds620_data *ret = data; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i; + int res; + + dev_dbg(&client->dev, "Starting ds620 update\n"); + + for (i = 0; i < ARRAY_SIZE(data->temp); i++) { + res = ds620_read_temp(client, + DS620_REG_TEMP[i]); + if (res < 0) { + ret = ERR_PTR(res); + goto abort; + } + + data->temp[i] = res; + } + + data->last_updated = jiffies; + data->valid = 1; + } +abort: + mutex_unlock(&data->update_lock); + + return ret; +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ds620_data *data = ds620_update_client(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + + return sprintf(buf, "%d\n", ((data->temp[attr->index] / 8) * 625) / 10); +} + +static ssize_t set_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int res; + long val; + + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ds620_data *data = i2c_get_clientdata(client); + + res = strict_strtol(buf, 10, &val); + + if (res) + return res; + + val = (val * 10 / 625) * 8; + + mutex_lock(&data->update_lock); + data->temp[attr->index] = val; + ds620_write_temp(client, DS620_REG_TEMP[attr->index], + data->temp[attr->index]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_alarm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ds620_data *data = ds620_update_client(dev); + struct i2c_client *client = to_i2c_client(dev); + u16 conf, new_conf; + int res; + + if (IS_ERR(data)) + return PTR_ERR(data); + + /* reset alarms if necessary */ + res = i2c_smbus_read_word_data(client, DS620_REG_CONF); + if (res < 0) + return res; + + conf = swab16(res); + new_conf = conf; + new_conf &= ~attr->index; + if (conf != new_conf) { + res = i2c_smbus_write_word_data(client, DS620_REG_CONF, + swab16(new_conf)); + if (res < 0) + return res; + } + + return sprintf(buf, "%d\n", !!(conf & attr->index)); +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, + DS620_REG_CONFIG_TLF); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, + DS620_REG_CONFIG_THF); + +static struct attribute *ds620_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group ds620_group = { + .attrs = ds620_attributes, +}; + +static int ds620_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ds620_data *data; + int err; + + data = kzalloc(sizeof(struct ds620_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Initialize the DS620 chip */ + ds620_init_client(client); + + /* Register sysfs hooks */ + err = sysfs_create_group(&client->dev.kobj, &ds620_group); + if (err) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove_files; + } + + dev_info(&client->dev, "temperature sensor found\n"); + + return 0; + +exit_remove_files: + sysfs_remove_group(&client->dev.kobj, &ds620_group); +exit_free: + kfree(data); +exit: + return err; +} + +static int ds620_remove(struct i2c_client *client) +{ + struct ds620_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ds620_group); + + kfree(data); + + return 0; +} + +static const struct i2c_device_id ds620_id[] = { + {"ds620", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ds620_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver ds620_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ds620", + }, + .probe = ds620_probe, + .remove = ds620_remove, + .id_table = ds620_id, +}; + +static int __init ds620_init(void) +{ + return i2c_add_driver(&ds620_driver); +} + +static void __exit ds620_exit(void) +{ + i2c_del_driver(&ds620_driver); +} + +MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); +MODULE_DESCRIPTION("DS620 driver"); +MODULE_LICENSE("GPL"); + +module_init(ds620_init); +module_exit(ds620_exit); diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 8dee3f38fdfb..5dea9faa1656 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -269,23 +269,30 @@ static int emc1403_detect(struct i2c_client *client, struct i2c_board_info *info) { int id; - /* Check if thermal chip is SMSC and EMC1403 */ + /* Check if thermal chip is SMSC and EMC1403 or EMC1423 */ id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG); if (id != 0x5d) return -ENODEV; + id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG); + switch (id) { + case 0x21: + strlcpy(info->type, "emc1403", I2C_NAME_SIZE); + break; + case 0x23: + strlcpy(info->type, "emc1423", I2C_NAME_SIZE); + break; /* Note: 0x25 is the 1404 which is very similar and this driver could be extended */ - id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG); - if (id != 0x21) + default: return -ENODEV; + } id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); if (id != 0x01) return -ENODEV; - strlcpy(info->type, "emc1403", I2C_NAME_SIZE); return 0; } @@ -342,6 +349,7 @@ static const unsigned short emc1403_address_list[] = { static const struct i2c_device_id emc1403_idtable[] = { { "emc1403", 0 }, + { "emc1423", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, emc1403_idtable); diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 525a00bd70b1..92f949767ece 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -28,6 +28,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -1309,7 +1311,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev) if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Out of memory\n"); + pr_err("Out of memory\n"); goto exit; } @@ -1451,7 +1453,7 @@ static int __init f71805f_device_add(unsigned short address, pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } @@ -1462,22 +1464,20 @@ static int __init f71805f_device_add(unsigned short address, err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add_data(pdev, sio_data, sizeof(struct f71805f_sio_data)); if (err) { - printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + pr_err("Platform data allocation failed\n"); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } @@ -1516,30 +1516,27 @@ static int __init f71805f_find(int sioaddr, unsigned short *address, sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1); break; default: - printk(KERN_INFO DRVNAME ": Unsupported Fintek device, " - "skipping\n"); + pr_info("Unsupported Fintek device, skipping\n"); goto exit; } superio_select(sioaddr, F71805F_LD_HWM); if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { - printk(KERN_WARNING DRVNAME ": Device not activated, " - "skipping\n"); + pr_warn("Device not activated, skipping\n"); goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { - printk(KERN_WARNING DRVNAME ": Base address not set, " - "skipping\n"); + pr_warn("Base address not set, skipping\n"); goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ err = 0; - printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n", - names[sio_data->kind], *address, - superio_inb(sioaddr, SIO_REG_DEVREV)); + pr_info("Found %s chip at %#x, revision %u\n", + names[sio_data->kind], *address, + superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 75afb3b0e076..3f49dd376f02 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -865,8 +867,7 @@ static inline int superio_enter(int base) { /* Don't step on other drivers' I/O space by accident */ if (!request_muxed_region(base, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - base); + pr_err("I/O address 0x%04x already in use\n", base); return -EBUSY; } @@ -2192,7 +2193,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { - pr_debug(DRVNAME ": Not a Fintek device\n"); + pr_debug("Not a Fintek device\n"); err = -ENODEV; goto exit; } @@ -2215,8 +2216,8 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, sio_data->type = f8000; break; default: - printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", - (unsigned int)devid); + pr_info("Unsupported Fintek device: %04x\n", + (unsigned int)devid); err = -ENODEV; goto exit; } @@ -2227,21 +2228,21 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, superio_select(sioaddr, SIO_F71882FG_LD_HWM); if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { - printk(KERN_WARNING DRVNAME ": Device not activated\n"); + pr_warn("Device not activated\n"); err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { - printk(KERN_WARNING DRVNAME ": Base address not set\n"); + pr_warn("Base address not set\n"); err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ err = 0; - printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", + pr_info("Found %s chip at %#x, revision %d\n", f71882fg_names[sio_data->type], (unsigned int)*address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: @@ -2270,20 +2271,20 @@ static int __init f71882fg_device_add(unsigned short address, err = platform_device_add_resources(f71882fg_pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed\n"); + pr_err("Device resource addition failed\n"); goto exit_device_put; } err = platform_device_add_data(f71882fg_pdev, sio_data, sizeof(struct f71882fg_sio_data)); if (err) { - printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + pr_err("Platform data allocation failed\n"); goto exit_device_put; } err = platform_device_add(f71882fg_pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed\n"); + pr_err("Device addition failed\n"); goto exit_device_put; } diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index d4d4ca65d371..aa6d8b686f82 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -49,7 +49,6 @@ #include <linux/kref.h> /* Addresses to scan */ -static DEFINE_MUTEX(watchdog_mutex); static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; /* Insmod parameters */ @@ -850,7 +849,7 @@ static ssize_t watchdog_write(struct file *filp, const char __user *buf, static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - static struct watchdog_info ident = { + struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_CARDRESET, .identity = "FSC watchdog" @@ -858,7 +857,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar int i, ret = 0; struct fschmd_data *data = filp->private_data; - mutex_lock(&watchdog_mutex); switch (cmd) { case WDIOC_GETSUPPORT: ident.firmware_version = data->revision; @@ -915,7 +913,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar default: ret = -ENOTTY; } - mutex_unlock(&watchdog_mutex); return ret; } diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index aa701a183707..f141a1de519c 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -376,10 +376,6 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data, } } - err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group); - if (err) - goto err_free_gpio; - fan_data->num_ctrl = num_ctrl; fan_data->ctrl = ctrl; fan_data->num_speed = pdata->num_speed; @@ -391,6 +387,10 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data, goto err_free_gpio; } + err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group); + if (err) + goto err_free_gpio; + return 0; err_free_gpio: diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index a56a78412fcb..3d21fa2b97cd 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -20,6 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/init.h> #include <linux/dmi.h> @@ -147,7 +149,7 @@ int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) { lis3_dev.ac = *((union axis_conversion *)dmi->driver_data); - printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); + pr_info("hardware type %s found\n", dmi->ident); return 1; } @@ -303,11 +305,10 @@ static int lis3lv02d_add(struct acpi_device *device) /* If possible use a "standard" axes order */ if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) { - printk(KERN_INFO DRIVER_NAME ": Using custom axes %d,%d,%d\n", - lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z); + pr_info("Using custom axes %d,%d,%d\n", + lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z); } else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { - printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " - "using default axes configuration\n"); + pr_info("laptop model unknown, using default axes configuration\n"); lis3_dev.ac = lis3lv02d_axis_normal; } @@ -385,7 +386,7 @@ static int __init lis3lv02d_init_module(void) if (ret < 0) return ret; - printk(KERN_INFO DRIVER_NAME " driver loaded.\n"); + pr_info("driver loaded\n"); return 0; } diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index 2b2ca1694f95..2582bfef6ccb 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -22,6 +22,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/hwmon-vid.h> @@ -146,8 +148,8 @@ int vid_from_reg(int val, u8 vrm) return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000); default: /* report 0 for unknown */ if (vrm) - printk(KERN_WARNING "hwmon-vid: Requested unsupported " - "VRM version (%u)\n", (unsigned int)vrm); + pr_warn("Requested unsupported VRM version (%u)\n", + (unsigned int)vrm); return 0; } } @@ -246,8 +248,7 @@ u8 vid_which_vrm(void) } vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor); if (vrm_ret == 0) - printk(KERN_INFO "hwmon-vid: Unknown VRM version of your " - "x86 CPU\n"); + pr_info("Unknown VRM version of your x86 CPU\n"); return vrm_ret; } @@ -255,7 +256,7 @@ u8 vid_which_vrm(void) #else u8 vid_which_vrm(void) { - printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n"); + pr_info("Unknown VRM version of your CPU\n"); return 0; } #endif diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 29ea6753f3bb..a61e7815a2a9 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -10,6 +10,8 @@ the Free Software Foundation; version 2 of the License. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/device.h> #include <linux/err.h> @@ -119,7 +121,7 @@ static int __init hwmon_init(void) hwmon_class = class_create(THIS_MODULE, "hwmon"); if (IS_ERR(hwmon_class)) { - printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n"); + pr_err("couldn't create sysfs class\n"); return PTR_ERR(hwmon_class); } return 0; diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index 937983407e2a..c4c40be0edbf 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -497,12 +497,14 @@ static unsigned long chipset_ids[] = { 0 }; +#ifdef MODULE static struct pci_device_id i5k_amb_ids[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) }, { 0, } }; MODULE_DEVICE_TABLE(pci, i5k_amb_ids); +#endif static int __devinit i5k_amb_probe(struct platform_device *pdev) { diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index eaee546af19a..bc6e2ab3a361 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -20,6 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/ipmi.h> #include <linux/module.h> #include <linux/hwmon.h> @@ -1090,7 +1092,7 @@ static int __init aem_init(void) res = driver_register(&aem_driver.driver); if (res) { - printk(KERN_ERR "Can't register aem driver\n"); + pr_err("Can't register aem driver\n"); return res; } diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 14a5d981be7d..316b64823f7b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -38,6 +38,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -187,6 +189,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; #define IT87_REG_FAN_MAIN_CTRL 0x13 #define IT87_REG_FAN_CTL 0x14 #define IT87_REG_PWM(nr) (0x15 + (nr)) +#define IT87_REG_PWM_DUTY(nr) (0x63 + (nr) * 8) #define IT87_REG_VIN(nr) (0x20 + (nr)) #define IT87_REG_TEMP(nr) (0x29 + (nr)) @@ -251,12 +254,16 @@ struct it87_data { u8 fan_main_ctrl; /* Register value */ u8 fan_ctl; /* Register value */ - /* The following 3 arrays correspond to the same registers. The - * meaning of bits 6-0 depends on the value of bit 7, and we want - * to preserve settings on mode changes, so we have to track all - * values separately. */ + /* The following 3 arrays correspond to the same registers up to + * the IT8720F. The meaning of bits 6-0 depends on the value of bit + * 7, and we want to preserve settings on mode changes, so we have + * to track all values separately. + * Starting with the IT8721F, the manual PWM duty cycles are stored + * in separate registers (8-bit values), so the separate tracking + * is no longer needed, but it is still done to keep the driver + * simple. */ u8 pwm_ctrl[3]; /* Register value */ - u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */ + u8 pwm_duty[3]; /* Manual PWM value set by user */ u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */ /* Automatic fan speed control registers */ @@ -832,7 +839,9 @@ static ssize_t set_pwm_enable(struct device *dev, data->fan_main_ctrl); } else { if (val == 1) /* Manual mode */ - data->pwm_ctrl[nr] = data->pwm_duty[nr]; + data->pwm_ctrl[nr] = data->type == it8721 ? + data->pwm_temp_map[nr] : + data->pwm_duty[nr]; else /* Automatic mode */ data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); @@ -858,12 +867,25 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, return -EINVAL; mutex_lock(&data->update_lock); - data->pwm_duty[nr] = pwm_to_reg(data, val); - /* If we are in manual mode, write the duty cycle immediately; - * otherwise, just store it for later use. */ - if (!(data->pwm_ctrl[nr] & 0x80)) { - data->pwm_ctrl[nr] = data->pwm_duty[nr]; - it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); + if (data->type == it8721) { + /* If we are in automatic mode, the PWM duty cycle register + * is read-only so we can't write the value */ + if (data->pwm_ctrl[nr] & 0x80) { + mutex_unlock(&data->update_lock); + return -EBUSY; + } + data->pwm_duty[nr] = pwm_to_reg(data, val); + it87_write_value(data, IT87_REG_PWM_DUTY(nr), + data->pwm_duty[nr]); + } else { + data->pwm_duty[nr] = pwm_to_reg(data, val); + /* If we are in manual mode, write the duty cycle immediately; + * otherwise, just store it for later use. */ + if (!(data->pwm_ctrl[nr] & 0x80)) { + data->pwm_ctrl[nr] = data->pwm_duty[nr]; + it87_write_value(data, IT87_REG_PWM(nr), + data->pwm_ctrl[nr]); + } } mutex_unlock(&data->update_lock); return count; @@ -1550,26 +1572,25 @@ static int __init it87_find(unsigned short *address, case 0xffff: /* No device at all */ goto exit; default: - pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", - chip_type); + pr_debug("Unsupported chip (DEVID=0x%x)\n", chip_type); goto exit; } superio_select(PME); if (!(superio_inb(IT87_ACT_REG) & 0x01)) { - pr_info("it87: Device not activated, skipping\n"); + pr_info("Device not activated, skipping\n"); goto exit; } *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1); if (*address == 0) { - pr_info("it87: Base address not set, skipping\n"); + pr_info("Base address not set, skipping\n"); goto exit; } err = 0; sio_data->revision = superio_inb(DEVREV) & 0x0f; - pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", + pr_info("Found IT%04xF chip at 0x%x, revision %d\n", chip_type, *address, sio_data->revision); /* in8 (Vbat) is always internal */ @@ -1595,7 +1616,7 @@ static int __init it87_find(unsigned short *address, } else { /* We need at least 4 VID pins */ if (reg & 0x0f) { - pr_info("it87: VID is disabled (pins used for GPIO)\n"); + pr_info("VID is disabled (pins used for GPIO)\n"); sio_data->skip_vid = 1; } } @@ -1631,7 +1652,7 @@ static int __init it87_find(unsigned short *address, if (sio_data->type == it8720 && !(reg & (1 << 1))) { reg |= (1 << 1); superio_outb(IT87_SIO_PINX2_REG, reg); - pr_notice("it87: Routing internal VCCH to in7\n"); + pr_notice("Routing internal VCCH to in7\n"); } if (reg & (1 << 0)) sio_data->internal |= (1 << 0); @@ -1641,7 +1662,7 @@ static int __init it87_find(unsigned short *address, sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; } if (sio_data->beep_pin) - pr_info("it87: Beeping is supported\n"); + pr_info("Beeping is supported\n"); /* Disable specific features based on DMI strings */ board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); @@ -1655,8 +1676,7 @@ static int __init it87_find(unsigned short *address, the PWM2 duty cycle, so we disable it. I use the board name string as the trigger in case the same board is ever used in other systems. */ - pr_info("it87: Disabling pwm2 due to " - "hardware constraints\n"); + pr_info("Disabling pwm2 due to hardware constraints\n"); sio_data->skip_pwm = (1 << 1); } } @@ -1958,7 +1978,10 @@ static void __devinit it87_init_device(struct platform_device *pdev) * channels to use when later setting to automatic mode later. * Use a 1:1 mapping by default (we are clueless.) * In both cases, the value can (and should) be changed by the user - * prior to switching to a different mode. */ + * prior to switching to a different mode. + * Note that this is no longer needed for the IT8721F and later, as + * these have separate registers for the temperature mapping and the + * manual duty cycle. */ for (i = 0; i < 3; i++) { data->pwm_temp_map[i] = i; data->pwm_duty[i] = 0x7f; /* Full speed */ @@ -2034,10 +2057,16 @@ static void __devinit it87_init_device(struct platform_device *pdev) static void it87_update_pwm_ctrl(struct it87_data *data, int nr) { data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); - if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ + if (data->type == it8721) { data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; - else /* Manual mode */ - data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; + data->pwm_duty[nr] = it87_read_value(data, + IT87_REG_PWM_DUTY(nr)); + } else { + if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ + data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; + else /* Manual mode */ + data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; + } if (has_old_autopwm(data)) { int i; @@ -2160,28 +2189,26 @@ static int __init it87_device_add(unsigned short address, pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add_data(pdev, sio_data, sizeof(struct it87_sio_data)); if (err) { - printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + pr_err("Platform data allocation failed\n"); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 0cee73a6124e..d805e8e57967 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -20,6 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/init.h> #include <linux/dmi.h> @@ -860,8 +862,7 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev, (p->irq_flags2 & IRQF_TRIGGER_MASK), DRIVER_NAME, &lis3_dev); if (err < 0) - printk(KERN_ERR DRIVER_NAME - "No second IRQ. Limited functionality\n"); + pr_err("No second IRQ. Limited functionality\n"); } } @@ -879,7 +880,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) switch (dev->whoami) { case WAI_12B: - printk(KERN_INFO DRIVER_NAME ": 12 bits sensor found\n"); + pr_info("12 bits sensor found\n"); dev->read_data = lis3lv02d_read_12; dev->mdps_max_val = 2048; dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B; @@ -890,7 +891,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) dev->regs_size = ARRAY_SIZE(lis3_wai12_regs); break; case WAI_8B: - printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n"); + pr_info("8 bits sensor found\n"); dev->read_data = lis3lv02d_read_8; dev->mdps_max_val = 128; dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; @@ -901,7 +902,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) dev->regs_size = ARRAY_SIZE(lis3_wai8_regs); break; case WAI_3DC: - printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n"); + pr_info("8 bits 3DC sensor found\n"); dev->read_data = lis3lv02d_read_8; dev->mdps_max_val = 128; dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; @@ -910,8 +911,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) dev->scale = LIS3_SENSITIVITY_8B; break; default: - printk(KERN_ERR DRIVER_NAME - ": unknown sensor type 0x%X\n", dev->whoami); + pr_err("unknown sensor type 0x%X\n", dev->whoami); return -EINVAL; } @@ -935,7 +935,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) } if (lis3lv02d_joystick_enable()) - printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); + pr_err("joystick initialization failed\n"); /* passing in platform specific data is purely optional and only * used by the SPI transport layer at the moment */ @@ -957,8 +957,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) /* bail if we did not get an IRQ from the bus layer */ if (!dev->irq) { - printk(KERN_ERR DRIVER_NAME - ": No IRQ. Disabling /dev/freefall\n"); + pr_debug("No IRQ. Disabling /dev/freefall\n"); goto out; } @@ -985,12 +984,12 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) DRIVER_NAME, &lis3_dev); if (err < 0) { - printk(KERN_ERR DRIVER_NAME "Cannot get IRQ\n"); + pr_err("Cannot get IRQ\n"); goto out; } if (misc_register(&lis3lv02d_misc_device)) - printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); + pr_err("misc_register failed\n"); out: return 0; } diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c index 9f4bae07f719..8853afce85ce 100644 --- a/drivers/hwmon/lis3lv02d_i2c.c +++ b/drivers/hwmon/lis3lv02d_i2c.c @@ -186,7 +186,7 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int lis3lv02d_i2c_suspend(struct device *dev) { struct i2c_client *client = container_of(dev, struct i2c_client, dev); @@ -213,12 +213,9 @@ static int lis3lv02d_i2c_resume(struct device *dev) return 0; } -#else -#define lis3lv02d_i2c_suspend NULL -#define lis3lv02d_i2c_resume NULL -#define lis3lv02d_i2c_shutdown NULL -#endif +#endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_RUNTIME static int lis3_i2c_runtime_suspend(struct device *dev) { struct i2c_client *client = container_of(dev, struct i2c_client, dev); @@ -236,6 +233,7 @@ static int lis3_i2c_runtime_resume(struct device *dev) lis3lv02d_poweron(lis3); return 0; } +#endif /* CONFIG_PM_RUNTIME */ static const struct i2c_device_id lis3lv02d_id[] = { {"lis3lv02d", 0 }, diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index fd108cfc05c7..3b84fb503053 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -24,6 +24,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> @@ -67,8 +69,7 @@ static ssize_t lm70_sense_temp(struct device *dev, */ status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2); if (status < 0) { - printk(KERN_WARNING - "spi_write_then_read failed with status %d\n", status); + pr_warn("spi_write_then_read failed with status %d\n", status); goto out; } raw = (rxbuf[0] << 8) + rxbuf[1]; diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 72ff2c4e757d..4cb24eafe318 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -19,6 +19,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -858,7 +860,7 @@ static int __init lm78_isa_found(unsigned short address) * individually for the probing phase. */ for (port = address; port < address + LM78_EXTENT; port++) { if (!request_region(port, 1, "lm78")) { - pr_debug("lm78: Failed to request port 0x%x\n", port); + pr_debug("Failed to request port 0x%x\n", port); goto release; } } @@ -920,7 +922,7 @@ static int __init lm78_isa_found(unsigned short address) found = 1; if (found) - pr_info("lm78: Found an %s chip at %#x\n", + pr_info("Found an %s chip at %#x\n", val & 0x80 ? "LM79" : "LM78", (int)address); release: @@ -942,21 +944,19 @@ static int __init lm78_isa_device_add(unsigned short address) pdev = platform_device_alloc("lm78", address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR "lm78: Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR "lm78: Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR "lm78: Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 6669255aadcf..3b43df418613 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -20,7 +20,7 @@ Adapted to 2.6.20 by Carsten Emde <cbe@osadl.org> Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab - Modified for mainline integration by Hans J. Koch <hjk@linutronix.de> + Modified for mainline integration by Hans J. Koch <hjk@hansjkoch.de> Copyright (c) 2007 Hans J. Koch, Linutronix GmbH This program is free software; you can redistribute it and/or modify @@ -135,6 +135,11 @@ #define LM93_MFR_ID 0x73 #define LM93_MFR_ID_PROTOTYPE 0x72 +/* LM94 REGISTER VALUES */ +#define LM94_MFR_ID_2 0x7a +#define LM94_MFR_ID 0x79 +#define LM94_MFR_ID_PROTOTYPE 0x78 + /* SMBus capabilities */ #define LM93_SMBUS_FUNC_FULL (I2C_FUNC_SMBUS_BYTE_DATA | \ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA) @@ -2504,6 +2509,7 @@ static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info) { struct i2c_adapter *adapter = client->adapter; int mfr, ver; + const char *name; if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN)) return -ENODEV; @@ -2517,13 +2523,23 @@ static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info) } ver = lm93_read_byte(client, LM93_REG_VER); - if (ver != LM93_MFR_ID && ver != LM93_MFR_ID_PROTOTYPE) { + switch (ver) { + case LM93_MFR_ID: + case LM93_MFR_ID_PROTOTYPE: + name = "lm93"; + break; + case LM94_MFR_ID_2: + case LM94_MFR_ID: + case LM94_MFR_ID_PROTOTYPE: + name = "lm94"; + break; + default: dev_dbg(&adapter->dev, "detect failed, bad version id 0x%02x!\n", ver); return -ENODEV; } - strlcpy(info->type, "lm93", I2C_NAME_SIZE); + strlcpy(info->type, name, I2C_NAME_SIZE); dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n", client->name, i2c_adapter_id(client->adapter), client->addr); @@ -2602,6 +2618,7 @@ static int lm93_remove(struct i2c_client *client) static const struct i2c_device_id lm93_id[] = { { "lm93", 0 }, + { "lm94", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, lm93_id); @@ -2629,7 +2646,7 @@ static void __exit lm93_exit(void) } MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>, " - "Hans J. Koch <hjk@linutronix.de"); + "Hans J. Koch <hjk@hansjkoch.de>"); MODULE_DESCRIPTION("LM93 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 464340f25496..1a6dfb6df1e7 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -1,13 +1,9 @@ /* - * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2008 Davide Rizzo <elpa-rizzo@gmail.com> + * Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com> * - * Based on the max1619 driver. The LM95241 is a sensor chip made by National - * Semiconductors. - * It reports up to three temperatures (its own plus up to - * two external ones). Complete datasheet can be - * obtained from National's website at: + * The LM95241 is a sensor chip made by National Semiconductors. + * It reports up to three temperatures (its own plus up to two external ones). + * Complete datasheet can be obtained from National's website at: * http://www.national.com/ds.cgi/LM/LM95241.pdf * * This program is free software; you can redistribute it and/or modify @@ -36,8 +32,10 @@ #include <linux/mutex.h> #include <linux/sysfs.h> +#define DEVNAME "lm95241" + static const unsigned short normal_i2c[] = { - 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; + 0x19, 0x2a, 0x2b, I2C_CLIENT_END }; /* LM95241 registers */ #define LM95241_REG_R_MAN_ID 0xFE @@ -46,7 +44,7 @@ static const unsigned short normal_i2c[] = { #define LM95241_REG_RW_CONFIG 0x03 #define LM95241_REG_RW_REM_FILTER 0x06 #define LM95241_REG_RW_TRUTHERM 0x07 -#define LM95241_REG_W_ONE_SHOT 0x0F +#define LM95241_REG_W_ONE_SHOT 0x0F #define LM95241_REG_R_LOCAL_TEMPH 0x10 #define LM95241_REG_R_REMOTE1_TEMPH 0x11 #define LM95241_REG_R_REMOTE2_TEMPH 0x12 @@ -79,226 +77,246 @@ static const unsigned short normal_i2c[] = { #define MANUFACTURER_ID 0x01 #define DEFAULT_REVISION 0xA4 -/* Conversions and various macros */ -#define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \ - (val_h)) * 1000 + (val_l) * 1000 / 256) - -/* Functions declaration */ -static void lm95241_init_client(struct i2c_client *client); -static struct lm95241_data *lm95241_update_device(struct device *dev); +static const u8 lm95241_reg_address[] = { + LM95241_REG_R_LOCAL_TEMPH, + LM95241_REG_R_LOCAL_TEMPL, + LM95241_REG_R_REMOTE1_TEMPH, + LM95241_REG_R_REMOTE1_TEMPL, + LM95241_REG_R_REMOTE2_TEMPH, + LM95241_REG_R_REMOTE2_TEMPL +}; /* Client data (each client gets its own) */ struct lm95241_data { struct device *hwmon_dev; struct mutex update_lock; - unsigned long last_updated, interval; /* in jiffies */ - char valid; /* zero until following fields are valid */ + unsigned long last_updated, interval; /* in jiffies */ + char valid; /* zero until following fields are valid */ /* registers values */ - u8 local_h, local_l; /* local */ - u8 remote1_h, remote1_l; /* remote1 */ - u8 remote2_h, remote2_l; /* remote2 */ + u8 temp[ARRAY_SIZE(lm95241_reg_address)]; u8 config, model, trutherm; }; +/* Conversions */ +static int TempFromReg(u8 val_h, u8 val_l) +{ + if (val_h & 0x80) + return val_h - 0x100; + return val_h * 1000 + val_l * 1000 / 256; +} + +static struct lm95241_data *lm95241_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + data->interval) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Updating lm95241 data.\n"); + for (i = 0; i < ARRAY_SIZE(lm95241_reg_address); i++) + data->temp[i] + = i2c_smbus_read_byte_data(client, + lm95241_reg_address[i]); + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + /* Sysfs stuff */ -#define show_temp(value) \ -static ssize_t show_##value(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct lm95241_data *data = lm95241_update_device(dev); \ - snprintf(buf, PAGE_SIZE - 1, "%d\n", \ - TEMP_FROM_REG(data->value##_h, data->value##_l)); \ - return strlen(buf); \ +static ssize_t show_input(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct lm95241_data *data = lm95241_update_device(dev); + + return snprintf(buf, PAGE_SIZE - 1, "%d\n", + TempFromReg(data->temp[to_sensor_dev_attr(attr)->index], + data->temp[to_sensor_dev_attr(attr)->index + 1])); } -show_temp(local); -show_temp(remote1); -show_temp(remote2); -static ssize_t show_interval(struct device *dev, struct device_attribute *attr, +static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) { - struct lm95241_data *data = lm95241_update_device(dev); + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); - snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ); - return strlen(buf); + return snprintf(buf, PAGE_SIZE - 1, + data->model & to_sensor_dev_attr(attr)->index ? "1\n" : "2\n"); } -static ssize_t set_interval(struct device *dev, struct device_attribute *attr, +static ssize_t set_type(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct lm95241_data *data = i2c_get_clientdata(client); + unsigned long val; + int shift; + u8 mask = to_sensor_dev_attr(attr)->index; + + if (strict_strtoul(buf, 10, &val) < 0) + return -EINVAL; + if (val != 1 && val != 2) + return -EINVAL; - strict_strtol(buf, 10, &data->interval); - data->interval = data->interval * HZ / 1000; + shift = mask == R1MS_MASK ? TT1_SHIFT : TT2_SHIFT; + + mutex_lock(&data->update_lock); + + data->trutherm &= ~(TT_MASK << shift); + if (val == 1) { + data->model |= mask; + data->trutherm |= (TT_ON << shift); + } else { + data->model &= ~mask; + data->trutherm |= (TT_OFF << shift); + } + data->valid = 0; + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, + data->model); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, + data->trutherm); + + mutex_unlock(&data->update_lock); return count; } -#define show_type(flag) \ -static ssize_t show_type##flag(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - snprintf(buf, PAGE_SIZE - 1, \ - data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \ - return strlen(buf); \ +static ssize_t show_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + return snprintf(buf, PAGE_SIZE - 1, + data->config & to_sensor_dev_attr(attr)->index ? + "-127000\n" : "0\n"); } -show_type(1); -show_type(2); - -#define show_min(flag) \ -static ssize_t show_min##flag(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - snprintf(buf, PAGE_SIZE - 1, \ - data->config & R##flag##DF_MASK ? \ - "-127000\n" : "0\n"); \ - return strlen(buf); \ + +static ssize_t set_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + long val; + + if (strict_strtol(buf, 10, &val) < 0) + return -EINVAL; + if (val < -128000) + return -EINVAL; + + mutex_lock(&data->update_lock); + + if (val < 0) + data->config |= to_sensor_dev_attr(attr)->index; + else + data->config &= ~to_sensor_dev_attr(attr)->index; + data->valid = 0; + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); + + mutex_unlock(&data->update_lock); + + return count; } -show_min(1); -show_min(2); - -#define show_max(flag) \ -static ssize_t show_max##flag(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - snprintf(buf, PAGE_SIZE - 1, \ - data->config & R##flag##DF_MASK ? \ - "127000\n" : "255000\n"); \ - return strlen(buf); \ + +static ssize_t show_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + return snprintf(buf, PAGE_SIZE - 1, + data->config & to_sensor_dev_attr(attr)->index ? + "127000\n" : "255000\n"); } -show_max(1); -show_max(2); - -#define set_type(flag) \ -static ssize_t set_type##flag(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - long val; \ - strict_strtol(buf, 10, &val); \ -\ - if ((val == 1) || (val == 2)) { \ -\ - mutex_lock(&data->update_lock); \ -\ - data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \ - if (val == 1) { \ - data->model |= R##flag##MS_MASK; \ - data->trutherm |= (TT_ON << TT##flag##_SHIFT); \ - } \ - else { \ - data->model &= ~R##flag##MS_MASK; \ - data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \ - } \ -\ - data->valid = 0; \ -\ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \ - data->model); \ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \ - data->trutherm); \ -\ - mutex_unlock(&data->update_lock); \ -\ - } \ - return count; \ + +static ssize_t set_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + long val; + + if (strict_strtol(buf, 10, &val) < 0) + return -EINVAL; + if (val >= 256000) + return -EINVAL; + + mutex_lock(&data->update_lock); + + if (val <= 127000) + data->config |= to_sensor_dev_attr(attr)->index; + else + data->config &= ~to_sensor_dev_attr(attr)->index; + data->valid = 0; + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); + + mutex_unlock(&data->update_lock); + + return count; } -set_type(1); -set_type(2); - -#define set_min(flag) \ -static ssize_t set_min##flag(struct device *dev, \ - struct device_attribute *devattr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - long val; \ - strict_strtol(buf, 10, &val); \ -\ - mutex_lock(&data->update_lock); \ -\ - if (val < 0) \ - data->config |= R##flag##DF_MASK; \ - else \ - data->config &= ~R##flag##DF_MASK; \ -\ - data->valid = 0; \ -\ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ - data->config); \ -\ - mutex_unlock(&data->update_lock); \ -\ - return count; \ + +static ssize_t show_interval(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct lm95241_data *data = lm95241_update_device(dev); + + return snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval + / HZ); } -set_min(1); -set_min(2); - -#define set_max(flag) \ -static ssize_t set_max##flag(struct device *dev, \ - struct device_attribute *devattr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - long val; \ - strict_strtol(buf, 10, &val); \ -\ - mutex_lock(&data->update_lock); \ -\ - if (val <= 127000) \ - data->config |= R##flag##DF_MASK; \ - else \ - data->config &= ~R##flag##DF_MASK; \ -\ - data->valid = 0; \ -\ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ - data->config); \ -\ - mutex_unlock(&data->update_lock); \ -\ - return count; \ + +static ssize_t set_interval(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + unsigned long val; + + if (strict_strtoul(buf, 10, &val) < 0) + return -EINVAL; + + data->interval = val * HZ / 1000; + + return count; } -set_max(1); -set_max(2); - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL); -static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL); -static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL); -static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1); -static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2); -static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); -static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); -static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); -static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type, + R1MS_MASK); +static SENSOR_DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type, + R2MS_MASK); +static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min, + R1DF_MASK); +static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min, + R2DF_MASK); +static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max, + R1DF_MASK); +static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max, + R2DF_MASK); static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, set_interval); static struct attribute *lm95241_attributes[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp3_input.attr, - &dev_attr_temp2_type.attr, - &dev_attr_temp3_type.attr, - &dev_attr_temp2_min.attr, - &dev_attr_temp3_min.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp3_max.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp2_type.dev_attr.attr, + &sensor_dev_attr_temp3_type.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, &dev_attr_update_interval.attr, NULL }; @@ -320,9 +338,9 @@ static int lm95241_detect(struct i2c_client *new_client, if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) == MANUFACTURER_ID) - && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) - >= DEFAULT_REVISION)) { - name = "lm95241"; + && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) + >= DEFAULT_REVISION)) { + name = DEVNAME; } else { dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n", address); @@ -334,6 +352,25 @@ static int lm95241_detect(struct i2c_client *new_client, return 0; } +static void lm95241_init_client(struct i2c_client *client) +{ + struct lm95241_data *data = i2c_get_clientdata(client); + + data->interval = HZ; /* 1 sec default */ + data->valid = 0; + data->config = CFG_CR0076; + data->model = 0; + data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, + R1FE_MASK | R2FE_MASK); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, + data->trutherm); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, + data->model); +} + static int lm95241_probe(struct i2c_client *new_client, const struct i2c_device_id *id) { @@ -373,26 +410,6 @@ exit: return err; } -static void lm95241_init_client(struct i2c_client *client) -{ - struct lm95241_data *data = i2c_get_clientdata(client); - - data->interval = HZ; /* 1 sec default */ - data->valid = 0; - data->config = CFG_CR0076; - data->model = 0; - data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); - - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, - data->config); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, - R1FE_MASK | R2FE_MASK); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, - data->trutherm); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, - data->model); -} - static int lm95241_remove(struct i2c_client *client) { struct lm95241_data *data = i2c_get_clientdata(client); @@ -404,46 +421,9 @@ static int lm95241_remove(struct i2c_client *client) return 0; } -static struct lm95241_data *lm95241_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + data->interval) || - !data->valid) { - dev_dbg(&client->dev, "Updating lm95241 data.\n"); - data->local_h = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_LOCAL_TEMPH); - data->local_l = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_LOCAL_TEMPL); - data->remote1_h = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE1_TEMPH); - data->remote1_l = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE1_TEMPL); - data->remote2_h = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE2_TEMPH); - data->remote2_l = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE2_TEMPL); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - /* Driver data (common to all clients) */ static const struct i2c_device_id lm95241_id[] = { - { "lm95241", 0 }, + { DEVNAME, 0 }, { } }; MODULE_DEVICE_TABLE(i2c, lm95241_id); @@ -451,7 +431,7 @@ MODULE_DEVICE_TABLE(i2c, lm95241_id); static struct i2c_driver lm95241_driver = { .class = I2C_CLASS_HWMON, .driver = { - .name = "lm95241", + .name = DEVNAME, }, .probe = lm95241_probe, .remove = lm95241_remove, @@ -470,7 +450,7 @@ static void __exit sensors_lm95241_exit(void) i2c_del_driver(&lm95241_driver); } -MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@gmail.com>"); +MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>"); MODULE_DESCRIPTION("LM95241 sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c index 00d975eb5b83..c7e6d8e81656 100644 --- a/drivers/hwmon/ltc4215.c +++ b/drivers/hwmon/ltc4215.c @@ -205,7 +205,6 @@ LTC4215_ALARM(curr1_max_alarm, (1 << 2), LTC4215_STATUS); /* Power (virtual) */ LTC4215_POWER(power1_input); -LTC4215_ALARM(power1_alarm, (1 << 3), LTC4215_STATUS); /* Input Voltage */ LTC4215_VOLTAGE(in1_input, LTC4215_ADIN); @@ -214,6 +213,7 @@ LTC4215_ALARM(in1_min_alarm, (1 << 1), LTC4215_STATUS); /* Output Voltage */ LTC4215_VOLTAGE(in2_input, LTC4215_SOURCE); +LTC4215_ALARM(in2_min_alarm, (1 << 3), LTC4215_STATUS); /* Finally, construct an array of pointers to members of the above objects, * as required for sysfs_create_group() @@ -223,13 +223,13 @@ static struct attribute *ltc4215_attributes[] = { &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, &sensor_dev_attr_power1_input.dev_attr.attr, - &sensor_dev_attr_power1_alarm.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_max_alarm.dev_attr.attr, &sensor_dev_attr_in1_min_alarm.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_min_alarm.dev_attr.attr, NULL, }; diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c index 267626178678..4b50601027d3 100644 --- a/drivers/hwmon/ltc4261.c +++ b/drivers/hwmon/ltc4261.c @@ -82,7 +82,7 @@ static struct ltc4261_data *ltc4261_update_device(struct device *dev) val = i2c_smbus_read_byte_data(client, i); if (unlikely(val < 0)) { dev_dbg(dev, - "Failed to read ADC value: error %d", + "Failed to read ADC value: error %d\n", val); ret = ERR_PTR(val); goto abort; @@ -230,8 +230,7 @@ static int ltc4261_probe(struct i2c_client *client, return -ENODEV; if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) { - dev_err(&client->dev, "Failed to read register %d:%02x:%02x\n", - adapter->id, client->addr, LTC4261_STATUS); + dev_err(&client->dev, "Failed to read status register\n"); return -ENODEV; } diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index a0160ee5caef..9a11532ecae8 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -2,7 +2,7 @@ * max6650.c - Part of lm_sensors, Linux kernel modules for hardware * monitoring. * - * (C) 2007 by Hans J. Koch <hjk@linutronix.de> + * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> * * based on code written by John Morris <john.morris@spirentcom.com> * Copyright (c) 2003 Spirent Communications diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 68e69a49633c..3d99b8854d7c 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -33,6 +33,8 @@ * the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F). */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -1031,16 +1033,15 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses val = superio_inb(sioaddr, ACT); if (!(val & 0x01)) { - printk(KERN_INFO "pc87360: Device 0x%02x not " - "activated\n", logdev[i]); + pr_info("Device 0x%02x not activated\n", logdev[i]); continue; } val = (superio_inb(sioaddr, BASE) << 8) | superio_inb(sioaddr, BASE + 1); if (!val) { - printk(KERN_INFO "pc87360: Base address not set for " - "device 0x%02x\n", logdev[i]); + pr_info("Base address not set for device 0x%02x\n", + logdev[i]); continue; } @@ -1050,17 +1051,15 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses confreg[0] = superio_inb(sioaddr, 0xF0); confreg[1] = superio_inb(sioaddr, 0xF1); -#ifdef DEBUG - printk(KERN_DEBUG "pc87360: Fan 1: mon=%d " - "ctrl=%d inv=%d\n", (confreg[0]>>2)&1, - (confreg[0]>>3)&1, (confreg[0]>>4)&1); - printk(KERN_DEBUG "pc87360: Fan 2: mon=%d " - "ctrl=%d inv=%d\n", (confreg[0]>>5)&1, - (confreg[0]>>6)&1, (confreg[0]>>7)&1); - printk(KERN_DEBUG "pc87360: Fan 3: mon=%d " - "ctrl=%d inv=%d\n", confreg[1]&1, - (confreg[1]>>1)&1, (confreg[1]>>2)&1); -#endif + pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 1, + (confreg[0] >> 2) & 1, (confreg[0] >> 3) & 1, + (confreg[0] >> 4) & 1); + pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 2, + (confreg[0] >> 5) & 1, (confreg[0] >> 6) & 1, + (confreg[0] >> 7) & 1); + pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3, + confreg[1] & 1, (confreg[1] >> 1) & 1, + (confreg[1] >> 2) & 1); } else if (i==1) { /* Voltages */ /* Are we using thermistors? */ if (*devid == 0xE9) { /* PC87366 */ @@ -1071,14 +1070,12 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses confreg[3] = superio_inb(sioaddr, 0x25); if (confreg[2] & 0x40) { - printk(KERN_INFO "pc87360: Using " - "thermistors for temperature " - "monitoring\n"); + pr_info("Using thermistors for " + "temperature monitoring\n"); } if (confreg[3] & 0xE0) { - printk(KERN_INFO "pc87360: VID " - "inputs routed (mode %u)\n", - confreg[3] >> 5); + pr_info("VID inputs routed (mode %u)\n", + confreg[3] >> 5); } } } @@ -1616,7 +1613,7 @@ static int __init pc87360_device_add(unsigned short address) pdev = platform_device_alloc("pc87360", address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR "pc87360: Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } @@ -1639,15 +1636,13 @@ static int __init pc87360_device_add(unsigned short address) err = platform_device_add_resources(pdev, res, res_count); if (err) { - printk(KERN_ERR "pc87360: Device resources addition failed " - "(%d)\n", err); + pr_err("Device resources addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR "pc87360: Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } @@ -1666,8 +1661,7 @@ static int __init pc87360_init(void) if (pc87360_find(0x2e, &devid, extra_isa) && pc87360_find(0x4e, &devid, extra_isa)) { - printk(KERN_WARNING "pc87360: PC8736x not detected, " - "module not inserted.\n"); + pr_warn("PC8736x not detected, module not inserted\n"); return -ENODEV; } @@ -1680,8 +1674,7 @@ static int __init pc87360_init(void) } if (address == 0x0000) { - printk(KERN_WARNING "pc87360: No active logical device, " - "module not inserted.\n"); + pr_warn("No active logical device, module not inserted\n"); return -ENODEV; } diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 9ec4daaf6ca6..8da2181630b1 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -22,6 +22,8 @@ * mode, and voltages aren't supported at all. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -1077,7 +1079,7 @@ static int __devinit pc87427_probe(struct platform_device *pdev) data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL); if (!data) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Out of memory\n"); + pr_err("Out of memory\n"); goto exit; } @@ -1196,28 +1198,26 @@ static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data) pdev = platform_device_alloc(DRVNAME, res[0].start); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, res, res_count); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add_data(pdev, sio_data, sizeof(struct pc87427_sio_data)); if (err) { - printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + pr_err("Platform data allocation failed\n"); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } @@ -1249,23 +1249,23 @@ static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data) val = superio_inb(sioaddr, SIOREG_ACT); if (!(val & 0x01)) { - printk(KERN_INFO DRVNAME ": Logical device 0x%02x " - "not activated\n", logdev[i]); + pr_info("Logical device 0x%02x not activated\n", + logdev[i]); continue; } val = superio_inb(sioaddr, SIOREG_MAP); if (val & 0x01) { - printk(KERN_WARNING DRVNAME ": Logical device 0x%02x " - "is memory-mapped, can't use\n", logdev[i]); + pr_warn("Logical device 0x%02x is memory-mapped, " + "can't use\n", logdev[i]); continue; } val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8) | superio_inb(sioaddr, SIOREG_IOBASE + 1); if (!val) { - printk(KERN_INFO DRVNAME ": I/O base address not set " - "for logical device 0x%02x\n", logdev[i]); + pr_info("I/O base address not set for logical device " + "0x%02x\n", logdev[i]); continue; } sio_data->address[i] = val; diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c index dc7259d69812..731b09af76b9 100644 --- a/drivers/hwmon/pcf8591.c +++ b/drivers/hwmon/pcf8591.c @@ -18,6 +18,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -290,8 +292,7 @@ static struct i2c_driver pcf8591_driver = { static int __init pcf8591_init(void) { if (input_mode < 0 || input_mode > 3) { - printk(KERN_WARNING "pcf8591: invalid input_mode (%d)\n", - input_mode); + pr_warn("invalid input_mode (%d)\n", input_mode); input_mode = 0; } return i2c_add_driver(&pcf8591_driver); diff --git a/drivers/hwmon/pkgtemp.c b/drivers/hwmon/pkgtemp.c index 0798210590bc..21c817d98123 100644 --- a/drivers/hwmon/pkgtemp.c +++ b/drivers/hwmon/pkgtemp.c @@ -20,6 +20,8 @@ * 02110-1301 USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -303,7 +305,7 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu) pdev = platform_device_alloc(DRVNAME, cpu); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } @@ -315,8 +317,7 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu) err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_free; } diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c index 05248f2d7581..92b42db43bcf 100644 --- a/drivers/hwmon/s3c-hwmon.c +++ b/drivers/hwmon/s3c-hwmon.c @@ -234,7 +234,6 @@ static int s3c_hwmon_create_attr(struct device *dev, attr->index = channel; attr->dev_attr.attr.name = attrs->in_name; attr->dev_attr.attr.mode = S_IRUGO; - attr->dev_attr.attr.owner = THIS_MODULE; attr->dev_attr.show = s3c_hwmon_ch_show; ret = device_create_file(dev, &attr->dev_attr); @@ -252,7 +251,6 @@ static int s3c_hwmon_create_attr(struct device *dev, attr->index = channel; attr->dev_attr.attr.name = attrs->label_name; attr->dev_attr.attr.mode = S_IRUGO; - attr->dev_attr.attr.owner = THIS_MODULE; attr->dev_attr.show = s3c_hwmon_label_show; ret = device_create_file(dev, &attr->dev_attr); diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c new file mode 100644 index 000000000000..1c8c9812f244 --- /dev/null +++ b/drivers/hwmon/sht21.c @@ -0,0 +1,307 @@ +/* Sensirion SHT21 humidity and temperature sensor driver + * + * Copyright (C) 2010 Urs Fleisch <urs.fleisch@sensirion.com> + * + * This program 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 program 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA + * + * Data sheet available (5/2010) at + * http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/device.h> + +/* I2C command bytes */ +#define SHT21_TRIG_T_MEASUREMENT_HM 0xe3 +#define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5 + +/** + * struct sht21 - SHT21 device specific data + * @hwmon_dev: device registered with hwmon + * @lock: mutex to protect measurement values + * @valid: only 0 before first measurement is taken + * @last_update: time of last update (jiffies) + * @temperature: cached temperature measurement value + * @humidity: cached humidity measurement value + */ +struct sht21 { + struct device *hwmon_dev; + struct mutex lock; + char valid; + unsigned long last_update; + int temperature; + int humidity; +}; + +/** + * sht21_temp_ticks_to_millicelsius() - convert raw temperature ticks to + * milli celsius + * @ticks: temperature ticks value received from sensor + */ +static inline int sht21_temp_ticks_to_millicelsius(int ticks) +{ + ticks &= ~0x0003; /* clear status bits */ + /* + * Formula T = -46.85 + 175.72 * ST / 2^16 from data sheet 6.2, + * optimized for integer fixed point (3 digits) arithmetic + */ + return ((21965 * ticks) >> 13) - 46850; +} + +/** + * sht21_rh_ticks_to_per_cent_mille() - convert raw humidity ticks to + * one-thousandths of a percent relative humidity + * @ticks: humidity ticks value received from sensor + */ +static inline int sht21_rh_ticks_to_per_cent_mille(int ticks) +{ + ticks &= ~0x0003; /* clear status bits */ + /* + * Formula RH = -6 + 125 * SRH / 2^16 from data sheet 6.1, + * optimized for integer fixed point (3 digits) arithmetic + */ + return ((15625 * ticks) >> 13) - 6000; +} + +/** + * sht21_read_word_data() - read word from register + * @client: I2C client device + * @reg: I2C command byte + * + * Returns value, negative errno on error. + */ +static inline int sht21_read_word_data(struct i2c_client *client, u8 reg) +{ + int ret = i2c_smbus_read_word_data(client, reg); + if (ret < 0) + return ret; + /* + * SMBus specifies low byte first, but the SHT21 returns MSB + * first, so we have to swab16 the values + */ + return swab16(ret); +} + +/** + * sht21_update_measurements() - get updated measurements from device + * @client: I2C client device + * + * Returns 0 on success, else negative errno. + */ +static int sht21_update_measurements(struct i2c_client *client) +{ + int ret = 0; + struct sht21 *sht21 = i2c_get_clientdata(client); + + mutex_lock(&sht21->lock); + /* + * Data sheet 2.4: + * SHT2x should not be active for more than 10% of the time - e.g. + * maximum two measurements per second at 12bit accuracy shall be made. + */ + if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) { + ret = sht21_read_word_data(client, SHT21_TRIG_T_MEASUREMENT_HM); + if (ret < 0) + goto out; + sht21->temperature = sht21_temp_ticks_to_millicelsius(ret); + ret = sht21_read_word_data(client, + SHT21_TRIG_RH_MEASUREMENT_HM); + if (ret < 0) + goto out; + sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret); + sht21->last_update = jiffies; + sht21->valid = 1; + } +out: + mutex_unlock(&sht21->lock); + + return ret >= 0 ? 0 : ret; +} + +/** + * sht21_show_temperature() - show temperature measurement value in sysfs + * @dev: device + * @attr: device attribute + * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to + * + * Will be called on read access to temp1_input sysfs attribute. + * Returns number of bytes written into buffer, negative errno on error. + */ +static ssize_t sht21_show_temperature(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sht21 *sht21 = i2c_get_clientdata(client); + int ret = sht21_update_measurements(client); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", sht21->temperature); +} + +/** + * sht21_show_humidity() - show humidity measurement value in sysfs + * @dev: device + * @attr: device attribute + * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to + * + * Will be called on read access to humidity1_input sysfs attribute. + * Returns number of bytes written into buffer, negative errno on error. + */ +static ssize_t sht21_show_humidity(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sht21 *sht21 = i2c_get_clientdata(client); + int ret = sht21_update_measurements(client); + if (ret < 0) + return ret; + return sprintf(buf, "%d\n", sht21->humidity); +} + +/* sysfs attributes */ +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature, + NULL, 0); +static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity, + NULL, 0); + +static struct attribute *sht21_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_humidity1_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group sht21_attr_group = { + .attrs = sht21_attributes, +}; + +/** + * sht21_probe() - probe device + * @client: I2C client device + * @id: device ID + * + * Called by the I2C core when an entry in the ID table matches a + * device's name. + * Returns 0 on success. + */ +static int __devinit sht21_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct sht21 *sht21; + int err; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WORD_DATA)) { + dev_err(&client->dev, + "adapter does not support SMBus word transactions\n"); + return -ENODEV; + } + + sht21 = kzalloc(sizeof(*sht21), GFP_KERNEL); + if (!sht21) { + dev_dbg(&client->dev, "kzalloc failed\n"); + return -ENOMEM; + } + i2c_set_clientdata(client, sht21); + + mutex_init(&sht21->lock); + + err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group); + if (err) { + dev_dbg(&client->dev, "could not create sysfs files\n"); + goto fail_free; + } + sht21->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(sht21->hwmon_dev)) { + dev_dbg(&client->dev, "unable to register hwmon device\n"); + err = PTR_ERR(sht21->hwmon_dev); + goto fail_remove_sysfs; + } + + dev_info(&client->dev, "initialized\n"); + + return 0; + +fail_remove_sysfs: + sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); +fail_free: + kfree(sht21); + + return err; +} + +/** + * sht21_remove() - remove device + * @client: I2C client device + */ +static int __devexit sht21_remove(struct i2c_client *client) +{ + struct sht21 *sht21 = i2c_get_clientdata(client); + + hwmon_device_unregister(sht21->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); + kfree(sht21); + + return 0; +} + +/* Device ID table */ +static const struct i2c_device_id sht21_id[] = { + { "sht21", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, sht21_id); + +static struct i2c_driver sht21_driver = { + .driver.name = "sht21", + .probe = sht21_probe, + .remove = __devexit_p(sht21_remove), + .id_table = sht21_id, +}; + +/** + * sht21_init() - initialize driver + * + * Called when kernel is booted or module is inserted. + * Returns 0 on success. + */ +static int __init sht21_init(void) +{ + return i2c_add_driver(&sht21_driver); +} +module_init(sht21_init); + +/** + * sht21_init() - clean up driver + * + * Called when module is removed. + */ +static void __exit sht21_exit(void) +{ + i2c_del_driver(&sht21_driver); +} +module_exit(sht21_exit); + +MODULE_AUTHOR("Urs Fleisch <urs.fleisch@sensirion.com>"); +MODULE_DESCRIPTION("Sensirion SHT21 humidity and temperature sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 79c2931e3008..47d7ce9af8fb 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -50,6 +50,8 @@ 735 0008 0735 */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/slab.h> #include <linux/ioport.h> @@ -735,21 +737,19 @@ static int __devinit sis5595_device_add(unsigned short address) pdev = platform_device_alloc("sis5595", address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR "sis5595: Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR "sis5595: Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR "sis5595: Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index f46d936c12da..9fb7516e6f45 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/slab.h> #include <linux/ioport.h> @@ -311,21 +313,19 @@ static int __init smsc47b397_device_add(unsigned short address) pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } @@ -367,8 +367,7 @@ static int __init smsc47b397_find(unsigned short *addr) *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) | superio_inb(SUPERIO_REG_BASE_LSB); - printk(KERN_INFO DRVNAME ": found SMSC %s " - "(base address 0x%04x, revision %u)\n", + pr_info("found SMSC %s (base address 0x%04x, revision %u)\n", name, *addr, rev); superio_exit(); diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 8fa462f2b570..f44a89aac381 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/slab.h> #include <linux/ioport.h> @@ -435,30 +437,29 @@ static int __init smsc47m1_find(unsigned short *addr, */ switch (val) { case 0x51: - pr_info(DRVNAME ": Found SMSC LPC47B27x\n"); + pr_info("Found SMSC LPC47B27x\n"); sio_data->type = smsc47m1; break; case 0x59: - pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n"); + pr_info("Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n"); sio_data->type = smsc47m1; break; case 0x5F: - pr_info(DRVNAME ": Found SMSC LPC47M14x\n"); + pr_info("Found SMSC LPC47M14x\n"); sio_data->type = smsc47m1; break; case 0x60: - pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n"); + pr_info("Found SMSC LPC47M15x/LPC47M192/LPC47M997\n"); sio_data->type = smsc47m1; break; case 0x6B: if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) { - pr_debug(DRVNAME ": " - "Found SMSC LPC47M233, unsupported\n"); + pr_debug("Found SMSC LPC47M233, unsupported\n"); superio_exit(); return -ENODEV; } - pr_info(DRVNAME ": Found SMSC LPC47M292\n"); + pr_info("Found SMSC LPC47M292\n"); sio_data->type = smsc47m2; break; default: @@ -470,7 +471,7 @@ static int __init smsc47m1_find(unsigned short *addr, *addr = (superio_inb(SUPERIO_REG_BASE) << 8) | superio_inb(SUPERIO_REG_BASE + 1); if (*addr == 0) { - pr_info(DRVNAME ": Device address not set, will not use\n"); + pr_info("Device address not set, will not use\n"); superio_exit(); return -ENODEV; } @@ -479,7 +480,7 @@ static int __init smsc47m1_find(unsigned short *addr, * Compaq Presario S4000NX) */ sio_data->activate = superio_inb(SUPERIO_REG_ACT); if ((sio_data->activate & 0x01) == 0) { - pr_info(DRVNAME ": Enabling device\n"); + pr_info("Enabling device\n"); superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01); } @@ -494,7 +495,7 @@ static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data) superio_enter(); superio_select(); - pr_info(DRVNAME ": Disabling device\n"); + pr_info("Disabling device\n"); superio_outb(SUPERIO_REG_ACT, sio_data->activate); superio_exit(); @@ -823,28 +824,26 @@ static int __init smsc47m1_device_add(unsigned short address, pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add_data(pdev, sio_data, sizeof(struct smsc47m1_sio_data)); if (err) { - printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + pr_err("Platform data allocation failed\n"); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index ec7fad747adc..0d18de424c66 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -21,6 +21,8 @@ * 02110-1301 USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -202,7 +204,7 @@ static int __cpuinit via_cputemp_device_add(unsigned int cpu) pdev = platform_device_alloc(DRVNAME, cpu); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } @@ -214,8 +216,7 @@ static int __cpuinit via_cputemp_device_add(unsigned int cpu) err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_free; } @@ -237,13 +238,16 @@ exit: static void __cpuinit via_cputemp_device_remove(unsigned int cpu) { - struct pdev_entry *p, *n; + struct pdev_entry *p; + mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { + list_for_each_entry(p, &pdev_list, list) { if (p->cpu == cpu) { platform_device_unregister(p->pdev); list_del(&p->list); + mutex_unlock(&pdev_list_mutex); kfree(p); + return; } } mutex_unlock(&pdev_list_mutex); @@ -273,7 +277,6 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = { static int __init via_cputemp_init(void) { int i, err; - struct pdev_entry *p, *n; if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) { printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n"); @@ -295,33 +298,27 @@ static int __init via_cputemp_init(void) continue; if (c->x86_model > 0x0f) { - printk(KERN_WARNING DRVNAME ": Unknown CPU " - "model 0x%x\n", c->x86_model); + pr_warn("Unknown CPU model 0x%x\n", c->x86_model); continue; } - err = via_cputemp_device_add(i); - if (err) - goto exit_devices_unreg; + via_cputemp_device_add(i); } + +#ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { err = -ENODEV; goto exit_driver_unreg; } +#endif register_hotcpu_notifier(&via_cputemp_cpu_notifier); return 0; -exit_devices_unreg: - mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { - platform_device_unregister(p->pdev); - list_del(&p->list); - kfree(p); - } - mutex_unlock(&pdev_list_mutex); +#ifndef CONFIG_HOTPLUG_CPU exit_driver_unreg: platform_driver_unregister(&via_cputemp_driver); +#endif exit: return err; } diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index f397ce7ad598..25e91665a0a2 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -30,6 +30,8 @@ Warning - only supports a single device. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/slab.h> #include <linux/pci.h> @@ -687,6 +689,13 @@ static int __devexit via686a_remove(struct platform_device *pdev) return 0; } +static void via686a_update_fan_div(struct via686a_data *data) +{ + int reg = via686a_read_value(data, VIA686A_REG_FANDIV); + data->fan_div[0] = (reg >> 4) & 0x03; + data->fan_div[1] = reg >> 6; +} + static void __devinit via686a_init_device(struct via686a_data *data) { u8 reg; @@ -700,6 +709,9 @@ static void __devinit via686a_init_device(struct via686a_data *data) via686a_write_value(data, VIA686A_REG_TEMP_MODE, (reg & ~VIA686A_TEMP_MODE_MASK) | VIA686A_TEMP_MODE_CONTINUOUS); + + /* Pre-read fan clock divisor values */ + via686a_update_fan_div(data); } static struct via686a_data *via686a_update_device(struct device *dev) @@ -751,9 +763,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & 0xc0) >> 6; - i = via686a_read_value(data, VIA686A_REG_FANDIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; + via686a_update_fan_div(data); data->alarms = via686a_read_value(data, VIA686A_REG_ALARM1) | @@ -791,21 +801,19 @@ static int __devinit via686a_device_add(unsigned short address) pdev = platform_device_alloc("via686a", address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR "via686a: Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR "via686a: Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR "via686a: Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index ae33bbb577c7..49163d48e966 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -21,6 +21,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -1254,8 +1256,7 @@ static int __init vt1211_device_add(unsigned short address) pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed (%d)\n", - err); + pr_err("Device allocation failed (%d)\n", err); goto EXIT; } @@ -1266,15 +1267,13 @@ static int __init vt1211_device_add(unsigned short address) err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto EXIT_DEV_PUT; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto EXIT_DEV_PUT; } @@ -1301,23 +1300,20 @@ static int __init vt1211_find(int sio_cip, unsigned short *address) superio_select(sio_cip, SIO_VT1211_LDN_HWMON); if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) { - printk(KERN_WARNING DRVNAME ": HW monitor is disabled, " - "skipping\n"); + pr_warn("HW monitor is disabled, skipping\n"); goto EXIT; } *address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) | (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00; if (*address == 0) { - printk(KERN_WARNING DRVNAME ": Base address is not set, " - "skipping\n"); + pr_warn("Base address is not set, skipping\n"); goto EXIT; } err = 0; - printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, " - "revision %u\n", *address, - superio_inb(sio_cip, SIO_VT1211_DEVREV)); + pr_info("Found VT1211 chip at 0x%04x, revision %u\n", + *address, superio_inb(sio_cip, SIO_VT1211_DEVREV)); EXIT: superio_exit(sio_cip); @@ -1336,15 +1332,15 @@ static int __init vt1211_init(void) if ((uch_config < -1) || (uch_config > 31)) { err = -EINVAL; - printk(KERN_WARNING DRVNAME ": Invalid UCH configuration %d. " - "Choose a value between 0 and 31.\n", uch_config); + pr_warn("Invalid UCH configuration %d. " + "Choose a value between 0 and 31.\n", uch_config); goto EXIT; } if ((int_mode < -1) || (int_mode > 0)) { err = -EINVAL; - printk(KERN_WARNING DRVNAME ": Invalid interrupt mode %d. " - "Only mode 0 is supported.\n", int_mode); + pr_warn("Invalid interrupt mode %d. " + "Only mode 0 is supported.\n", int_mode); goto EXIT; } diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index e6078c9f0e27..db3b2e8d2a67 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -24,6 +24,8 @@ /* Supports VIA VT8231 South Bridge embedded sensors */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -902,21 +904,19 @@ static int __devinit vt8231_device_add(unsigned short address) pdev = platform_device_alloc("vt8231", address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR "vt8231: Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR "vt8231: Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR "vt8231: Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 072c58008a63..073eabedc432 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -42,6 +42,8 @@ w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3 */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -1668,8 +1670,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, break; default: if (val != 0xffff) - pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", - val); + pr_debug("unsupported chip ID: 0x%04x\n", val); superio_exit(sioaddr); return -ENODEV; } @@ -1680,8 +1681,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, | superio_inb(sioaddr, SIO_REG_ADDR + 1); *addr = val & IOREGION_ALIGNMENT; if (*addr == 0) { - printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O " - "device with a base I/O port 0.\n"); + pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n"); superio_exit(sioaddr); return -ENODEV; } @@ -1689,13 +1689,12 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, /* Activate logical device if needed */ val = superio_inb(sioaddr, SIO_REG_ENABLE); if (!(val & 0x01)) { - printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. " - "Sensor is probably unusable.\n"); + pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n"); superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); } superio_exit(sioaddr); - pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, *addr); + pr_info("Found %s chip at %#x\n", sio_name, *addr); sio_data->sioreg = sioaddr; return 0; @@ -1729,14 +1728,14 @@ static int __init sensors_w83627ehf_init(void) if (!(pdev = platform_device_alloc(DRVNAME, address))) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit_unregister; } err = platform_device_add_data(pdev, &sio_data, sizeof(struct w83627ehf_sio_data)); if (err) { - printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + pr_err("Platform data allocation failed\n"); goto exit_device_put; } @@ -1752,16 +1751,14 @@ static int __init sensors_w83627ehf_init(void) err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } /* platform_device_add calls probe() */ err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 38e280523071..bde50e34d013 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -39,6 +39,8 @@ supported yet. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -1166,14 +1168,13 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, superio_inb(sio_data, WINB_BASE_REG + 1); *addr = val & WINB_ALIGNMENT; if (*addr == 0) { - printk(KERN_WARNING DRVNAME ": Base address not set, " - "skipping\n"); + pr_warn("Base address not set, skipping\n"); goto exit; } val = superio_inb(sio_data, WINB_ACT_REG); if (!(val & 0x01)) { - printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n"); + pr_warn("Enabling HWM logical device\n"); superio_outb(sio_data, WINB_ACT_REG, val | 0x01); } @@ -1789,28 +1790,26 @@ static int __init w83627hf_device_add(unsigned short address, pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add_data(pdev, sio_data, sizeof(struct w83627hf_sio_data)); if (err) { - printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + pr_err("Platform data allocation failed\n"); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index c84b9b4e6960..eed43a008be1 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -33,6 +33,8 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -1798,8 +1800,7 @@ w83781d_isa_found(unsigned short address) * individually for the probing phase. */ for (port = address; port < address + W83781D_EXTENT; port++) { if (!request_region(port, 1, "w83781d")) { - pr_debug("w83781d: Failed to request port 0x%x\n", - port); + pr_debug("Failed to request port 0x%x\n", port); goto release; } } @@ -1811,7 +1812,7 @@ w83781d_isa_found(unsigned short address) if (inb_p(address + 2) != val || inb_p(address + 3) != val || inb_p(address + 7) != val) { - pr_debug("w83781d: Detection failed at step 1\n"); + pr_debug("Detection failed at step %d\n", 1); goto release; } #undef REALLY_SLOW_IO @@ -1820,14 +1821,14 @@ w83781d_isa_found(unsigned short address) MSB (busy flag) should be clear initially, set after the write. */ save = inb_p(address + W83781D_ADDR_REG_OFFSET); if (save & 0x80) { - pr_debug("w83781d: Detection failed at step 2\n"); + pr_debug("Detection failed at step %d\n", 2); goto release; } val = ~save & 0x7f; outb_p(val, address + W83781D_ADDR_REG_OFFSET); if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { outb_p(save, address + W83781D_ADDR_REG_OFFSET); - pr_debug("w83781d: Detection failed at step 3\n"); + pr_debug("Detection failed at step %d\n", 3); goto release; } @@ -1835,7 +1836,7 @@ w83781d_isa_found(unsigned short address) outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); val = inb_p(address + W83781D_DATA_REG_OFFSET); if (val & 0x80) { - pr_debug("w83781d: Detection failed at step 4\n"); + pr_debug("Detection failed at step %d\n", 4); goto release; } outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); @@ -1844,19 +1845,19 @@ w83781d_isa_found(unsigned short address) val = inb_p(address + W83781D_DATA_REG_OFFSET); if ((!(save & 0x80) && (val != 0xa3)) || ((save & 0x80) && (val != 0x5c))) { - pr_debug("w83781d: Detection failed at step 5\n"); + pr_debug("Detection failed at step %d\n", 5); goto release; } outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); val = inb_p(address + W83781D_DATA_REG_OFFSET); if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ - pr_debug("w83781d: Detection failed at step 6\n"); + pr_debug("Detection failed at step %d\n", 6); goto release; } /* The busy flag should be clear again */ if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { - pr_debug("w83781d: Detection failed at step 7\n"); + pr_debug("Detection failed at step %d\n", 7); goto release; } @@ -1871,7 +1872,7 @@ w83781d_isa_found(unsigned short address) found = 1; if (found) - pr_info("w83781d: Found a %s chip at %#x\n", + pr_info("Found a %s chip at %#x\n", val == 0x30 ? "W83782D" : "W83781D", (int)address); release: @@ -1894,21 +1895,19 @@ w83781d_isa_device_add(unsigned short address) pdev = platform_device_alloc("w83781d", address); if (!pdev) { err = -ENOMEM; - printk(KERN_ERR "w83781d: Device allocation failed\n"); + pr_err("Device allocation failed\n"); goto exit; } err = platform_device_add_resources(pdev, &res, 1); if (err) { - printk(KERN_ERR "w83781d: Device resource addition failed " - "(%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(pdev); if (err) { - printk(KERN_ERR "w83781d: Device addition failed (%d)\n", - err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 679718e6b017..63841f8cec07 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -691,7 +691,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, } static ssize_t -show_regs_chassis(struct device *dev, struct device_attribute *attr, +show_chassis(struct device *dev, struct device_attribute *attr, char *buf) { struct w83792d_data *data = w83792d_update_device(dev); @@ -699,6 +699,16 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr, } static ssize_t +show_regs_chassis(struct device *dev, struct device_attribute *attr, + char *buf) +{ + dev_warn(dev, + "Attribute %s is deprecated, use intrusion0_alarm instead\n", + "chassis"); + return show_chassis(dev, attr, buf); +} + +static ssize_t show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) { struct w83792d_data *data = w83792d_update_device(dev); @@ -706,7 +716,7 @@ show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -store_chassis_clear(struct device *dev, struct device_attribute *attr, +store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); @@ -714,6 +724,10 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, u32 val; u8 temp1 = 0, temp2 = 0; + dev_warn(dev, + "Attribute %s is deprecated, use intrusion0_alarm instead\n", + "chassis_clear"); + val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); @@ -726,6 +740,27 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t +store_chassis_clear(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83792d_data *data = i2c_get_clientdata(client); + unsigned long val; + u8 reg; + + if (strict_strtoul(buf, 10, &val) || val != 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + reg = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR); + w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, reg | 0x80); + data->valid = 0; /* Force cache refresh */ + mutex_unlock(&data->update_lock); + + return count; +} + /* For Smart Fan I / Thermal Cruise */ static ssize_t show_thermal_cruise(struct device *dev, struct device_attribute *attr, @@ -1012,7 +1047,9 @@ static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22); static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, - show_chassis_clear, store_chassis_clear); + show_chassis_clear, store_chassis_clear_legacy); +static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, + show_chassis, store_chassis_clear); static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2); @@ -1214,6 +1251,7 @@ static struct attribute *w83792d_attributes[] = { &dev_attr_alarms.attr, &dev_attr_chassis.attr, &dev_attr_chassis_clear.attr, + &dev_attr_intrusion0_alarm.attr, &sensor_dev_attr_tolerance1.dev_attr.attr, &sensor_dev_attr_thermal_cruise1.dev_attr.attr, &sensor_dev_attr_tolerance2.dev_attr.attr, diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 8e540ada47d2..e3bdedfb5347 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -51,7 +51,6 @@ #define WATCHDOG_TIMEOUT 2 /* 2 minute default timeout */ /* Addresses to scan */ -static DEFINE_MUTEX(watchdog_mutex); static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; @@ -421,14 +420,17 @@ store_beep_enable(struct device *dev, struct device_attribute *attr, /* Write any value to clear chassis alarm */ static ssize_t -store_chassis_clear(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) +store_chassis_clear_legacy(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { struct i2c_client *client = to_i2c_client(dev); struct w83793_data *data = i2c_get_clientdata(client); u8 val; + dev_warn(dev, "Attribute chassis is deprecated, " + "use intrusion0_alarm instead\n"); + mutex_lock(&data->update_lock); val = w83793_read_value(client, W83793_REG_CLR_CHASSIS); val |= 0x80; @@ -437,6 +439,28 @@ store_chassis_clear(struct device *dev, return count; } +/* Write 0 to clear chassis alarm */ +static ssize_t +store_chassis_clear(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83793_data *data = i2c_get_clientdata(client); + unsigned long val; + u8 reg; + + if (strict_strtoul(buf, 10, &val) || val != 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + reg = w83793_read_value(client, W83793_REG_CLR_CHASSIS); + w83793_write_value(client, W83793_REG_CLR_CHASSIS, reg | 0x80); + data->valid = 0; /* Force cache refresh */ + mutex_unlock(&data->update_lock); + return count; +} + #define FAN_INPUT 0 #define FAN_MIN 1 static ssize_t @@ -1102,6 +1126,8 @@ static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm); static struct sensor_device_attribute_2 sda_single_files[] = { SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, + store_chassis_clear_legacy, ALARM_STATUS, 30), + SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, store_chassis_clear, ALARM_STATUS, 30), SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable, store_beep_enable, NOT_USED, NOT_USED), @@ -1323,7 +1349,7 @@ static ssize_t watchdog_write(struct file *filp, const char __user *buf, static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - static struct watchdog_info ident = { + struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_CARDRESET, @@ -1333,7 +1359,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, int val, ret = 0; struct w83793_data *data = filp->private_data; - mutex_lock(&watchdog_mutex); switch (cmd) { case WDIOC_GETSUPPORT: if (!nowayout) @@ -1387,7 +1412,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, default: ret = -ENOTTY; } - mutex_unlock(&watchdog_mutex); return ret; } diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 1d840aa83782..845232d7f611 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c @@ -165,10 +165,14 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = { #define W83795_REG_VID_CTRL 0x6A +#define W83795_REG_ALARM_CTRL 0x40 +#define ALARM_CTRL_RTSACS (1 << 7) #define W83795_REG_ALARM(index) (0x41 + (index)) +#define W83795_REG_CLR_CHASSIS 0x4D #define W83795_REG_BEEP(index) (0x50 + (index)) -#define W83795_REG_CLR_CHASSIS 0x4D +#define W83795_REG_OVT_CFG 0x58 +#define OVT_CFG_SEL (1 << 7) #define W83795_REG_FCMS1 0x201 @@ -178,6 +182,14 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = { #define W83795_REG_TSS(index) (0x209 + (index)) +#define TSS_MAP_RESERVED 0xff +static const u8 tss_map[4][6] = { + { 0, 1, 2, 3, 4, 5}, + { 6, 7, 8, 9, 0, 1}, + {10, 11, 12, 13, 2, 3}, + { 4, 5, 4, 5, TSS_MAP_RESERVED, TSS_MAP_RESERVED}, +}; + #define PWM_OUTPUT 0 #define PWM_FREQ 1 #define PWM_START 2 @@ -369,6 +381,7 @@ struct w83795_data { u8 setup_pwm[3]; /* Register value */ u8 alarms[6]; /* Register value */ + u8 enable_beep; u8 beeps[6]; /* Register value */ char valid; @@ -445,6 +458,7 @@ static void w83795_update_limits(struct i2c_client *client) { struct w83795_data *data = i2c_get_clientdata(client); int i, limit; + u8 lsb; /* Read the voltage limits */ for (i = 0; i < ARRAY_SIZE(data->in); i++) { @@ -466,9 +480,8 @@ static void w83795_update_limits(struct i2c_client *client) } /* Read the fan limits */ + lsb = 0; /* Silent false gcc warning */ for (i = 0; i < ARRAY_SIZE(data->fan); i++) { - u8 lsb; - /* Each register contains LSB for 2 fans, but we want to * read it only once to save time */ if ((i & 1) == 0 && (data->has_fan & (3 << i))) @@ -499,8 +512,11 @@ static void w83795_update_limits(struct i2c_client *client) } /* Read beep settings */ - for (i = 0; i < ARRAY_SIZE(data->beeps); i++) - data->beeps[i] = w83795_read(client, W83795_REG_BEEP(i)); + if (data->enable_beep) { + for (i = 0; i < ARRAY_SIZE(data->beeps); i++) + data->beeps[i] = + w83795_read(client, W83795_REG_BEEP(i)); + } data->valid_limits = 1; } @@ -577,6 +593,7 @@ static struct w83795_data *w83795_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct w83795_data *data = i2c_get_clientdata(client); u16 tmp; + u8 intrusion; int i; mutex_lock(&data->update_lock); @@ -648,9 +665,24 @@ static struct w83795_data *w83795_update_device(struct device *dev) w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT)); } - /* update alarm */ + /* Update intrusion and alarms + * It is important to read intrusion first, because reading from + * register SMI STS6 clears the interrupt status temporarily. */ + tmp = w83795_read(client, W83795_REG_ALARM_CTRL); + /* Switch to interrupt status for intrusion if needed */ + if (tmp & ALARM_CTRL_RTSACS) + w83795_write(client, W83795_REG_ALARM_CTRL, + tmp & ~ALARM_CTRL_RTSACS); + intrusion = w83795_read(client, W83795_REG_ALARM(5)) & (1 << 6); + /* Switch to real-time alarms */ + w83795_write(client, W83795_REG_ALARM_CTRL, tmp | ALARM_CTRL_RTSACS); for (i = 0; i < ARRAY_SIZE(data->alarms); i++) data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i)); + data->alarms[5] |= intrusion; + /* Restore original configuration if needed */ + if (!(tmp & ALARM_CTRL_RTSACS)) + w83795_write(client, W83795_REG_ALARM_CTRL, + tmp & ~ALARM_CTRL_RTSACS); data->last_updated = jiffies; data->valid = 1; @@ -730,6 +762,10 @@ store_chassis_clear(struct device *dev, val = w83795_read(client, W83795_REG_CLR_CHASSIS); val |= 0x80; w83795_write(client, W83795_REG_CLR_CHASSIS, val); + + /* Clear status and force cache refresh */ + w83795_read(client, W83795_REG_ALARM(5)); + data->valid = 0; mutex_unlock(&data->update_lock); return count; } @@ -857,20 +893,20 @@ show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) int index = sensor_attr->index; u8 tmp; - if (1 == (data->pwm_fcms[0] & (1 << index))) { + /* Speed cruise mode */ + if (data->pwm_fcms[0] & (1 << index)) { tmp = 2; goto out; } + /* Thermal cruise or SmartFan IV mode */ for (tmp = 0; tmp < 6; tmp++) { if (data->pwm_tfmr[tmp] & (1 << index)) { tmp = 3; goto out; } } - if (data->pwm_fomc & (1 << index)) - tmp = 0; - else - tmp = 1; + /* Manual mode */ + tmp = 1; out: return sprintf(buf, "%u\n", tmp); @@ -890,23 +926,21 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, if (strict_strtoul(buf, 10, &val) < 0) return -EINVAL; - if (val > 2) + if (val < 1 || val > 2) return -EINVAL; mutex_lock(&data->update_lock); switch (val) { - case 0: case 1: + /* Clear speed cruise mode bits */ data->pwm_fcms[0] &= ~(1 << index); w83795_write(client, W83795_REG_FCMS1, data->pwm_fcms[0]); + /* Clear thermal cruise mode bits */ for (i = 0; i < 6; i++) { data->pwm_tfmr[i] &= ~(1 << index); w83795_write(client, W83795_REG_TFMR(i), data->pwm_tfmr[i]); } - data->pwm_fomc |= 1 << index; - data->pwm_fomc ^= val << index; - w83795_write(client, W83795_REG_FOMC, data->pwm_fomc); break; case 2: data->pwm_fcms[0] |= (1 << index); @@ -918,23 +952,60 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, } static ssize_t +show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83795_data *data = w83795_update_pwm_config(dev); + int index = to_sensor_dev_attr_2(attr)->index; + unsigned int mode; + + if (data->pwm_fomc & (1 << index)) + mode = 0; /* DC */ + else + mode = 1; /* PWM */ + + return sprintf(buf, "%u\n", mode); +} + +/* + * Check whether a given temperature source can ever be useful. + * Returns the number of selectable temperature channels which are + * enabled. + */ +static int w83795_tss_useful(const struct w83795_data *data, int tsrc) +{ + int useful = 0, i; + + for (i = 0; i < 4; i++) { + if (tss_map[i][tsrc] == TSS_MAP_RESERVED) + continue; + if (tss_map[i][tsrc] < 6) /* Analog */ + useful += (data->has_temp >> tss_map[i][tsrc]) & 1; + else /* Digital */ + useful += (data->has_dts >> (tss_map[i][tsrc] - 6)) & 1; + } + + return useful; +} + +static ssize_t show_temp_src(struct device *dev, struct device_attribute *attr, char *buf) { struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); struct w83795_data *data = w83795_update_pwm_config(dev); int index = sensor_attr->index; - u8 val = index / 2; - u8 tmp = data->temp_src[val]; + u8 tmp = data->temp_src[index / 2]; if (index & 1) - val = 4; + tmp >>= 4; /* Pick high nibble */ else - val = 0; - tmp >>= val; - tmp &= 0x0f; + tmp &= 0x0f; /* Pick low nibble */ - return sprintf(buf, "%u\n", tmp); + /* Look-up the actual temperature channel number */ + if (tmp >= 4 || tss_map[tmp][index] == TSS_MAP_RESERVED) + return -EINVAL; /* Shouldn't happen */ + + return sprintf(buf, "%u\n", (unsigned int)tss_map[tmp][index] + 1); } static ssize_t @@ -946,12 +1017,21 @@ store_temp_src(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); int index = sensor_attr->index; - unsigned long tmp; + int tmp; + unsigned long channel; u8 val = index / 2; - if (strict_strtoul(buf, 10, &tmp) < 0) + if (strict_strtoul(buf, 10, &channel) < 0 || + channel < 1 || channel > 14) + return -EINVAL; + + /* Check if request can be fulfilled */ + for (tmp = 0; tmp < 4; tmp++) { + if (tss_map[tmp][index] == channel - 1) + break; + } + if (tmp == 4) /* No match */ return -EINVAL; - tmp = SENSORS_LIMIT(tmp, 0, 15); mutex_lock(&data->update_lock); if (index & 1) { @@ -1515,7 +1595,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, #define NOT_USED -1 -/* Don't change the attribute order, _max and _min are accessed by index +/* Don't change the attribute order, _max, _min and _beep are accessed by index * somewhere else in the code */ #define SENSOR_ATTR_IN(index) { \ SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \ @@ -1530,6 +1610,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, show_alarm_beep, store_beep, BEEP_ENABLE, \ index + ((index > 14) ? 1 : 0)) } +/* Don't change the attribute order, _beep is accessed by index + * somewhere else in the code */ #define SENSOR_ATTR_FAN(index) { \ SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \ NULL, FAN_INPUT, index - 1), \ @@ -1553,9 +1635,13 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, show_pwm, store_pwm, PWM_FREQ, index - 1), \ SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \ show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \ + SENSOR_ATTR_2(pwm##index##_mode, S_IRUGO, \ + show_pwm_mode, NULL, NOT_USED, index - 1), \ SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \ show_fanin, store_fanin, FANIN_TARGET, index - 1) } +/* Don't change the attribute order, _beep is accessed by index + * somewhere else in the code */ #define SENSOR_ATTR_DTS(index) { \ SENSOR_ATTR_2(temp##index##_type, S_IRUGO , \ show_dts_mode, NULL, NOT_USED, index - 7), \ @@ -1574,6 +1660,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) } +/* Don't change the attribute order, _beep is accessed by index + * somewhere else in the code */ #define SENSOR_ATTR_TEMP(index) { \ SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \ show_temp_mode, store_temp_mode, NOT_USED, index - 1), \ @@ -1593,8 +1681,6 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ show_alarm_beep, store_beep, BEEP_ENABLE, \ index + (index > 4 ? 11 : 17)), \ - SENSOR_ATTR_2(temp##index##_source_sel, S_IWUSR | S_IRUGO, \ - show_temp_src, store_temp_src, NOT_USED, index - 1), \ SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO, \ show_temp_pwm_enable, store_temp_pwm_enable, \ TEMP_PWM_ENABLE, index - 1), \ @@ -1680,7 +1766,7 @@ static const struct sensor_device_attribute_2 w83795_fan[][4] = { SENSOR_ATTR_FAN(14), }; -static const struct sensor_device_attribute_2 w83795_temp[][29] = { +static const struct sensor_device_attribute_2 w83795_temp[][28] = { SENSOR_ATTR_TEMP(1), SENSOR_ATTR_TEMP(2), SENSOR_ATTR_TEMP(3), @@ -1700,7 +1786,7 @@ static const struct sensor_device_attribute_2 w83795_dts[][8] = { SENSOR_ATTR_DTS(14), }; -static const struct sensor_device_attribute_2 w83795_pwm[][7] = { +static const struct sensor_device_attribute_2 w83795_pwm[][8] = { SENSOR_ATTR_PWM(1), SENSOR_ATTR_PWM(2), SENSOR_ATTR_PWM(3), @@ -1711,13 +1797,24 @@ static const struct sensor_device_attribute_2 w83795_pwm[][7] = { SENSOR_ATTR_PWM(8), }; +static const struct sensor_device_attribute_2 w83795_tss[6] = { + SENSOR_ATTR_2(temp1_source_sel, S_IWUSR | S_IRUGO, + show_temp_src, store_temp_src, NOT_USED, 0), + SENSOR_ATTR_2(temp2_source_sel, S_IWUSR | S_IRUGO, + show_temp_src, store_temp_src, NOT_USED, 1), + SENSOR_ATTR_2(temp3_source_sel, S_IWUSR | S_IRUGO, + show_temp_src, store_temp_src, NOT_USED, 2), + SENSOR_ATTR_2(temp4_source_sel, S_IWUSR | S_IRUGO, + show_temp_src, store_temp_src, NOT_USED, 3), + SENSOR_ATTR_2(temp5_source_sel, S_IWUSR | S_IRUGO, + show_temp_src, store_temp_src, NOT_USED, 4), + SENSOR_ATTR_2(temp6_source_sel, S_IWUSR | S_IRUGO, + show_temp_src, store_temp_src, NOT_USED, 5), +}; + static const struct sensor_device_attribute_2 sda_single_files[] = { SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, store_chassis_clear, ALARM_STATUS, 46), - SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep, - store_beep, BEEP_ENABLE, 46), - SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep, - store_beep, BEEP_ENABLE, 47), #ifdef CONFIG_SENSORS_W83795_FANCTRL SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin, store_fanin, FANIN_TOL, NOT_USED), @@ -1730,6 +1827,13 @@ static const struct sensor_device_attribute_2 sda_single_files[] = { #endif }; +static const struct sensor_device_attribute_2 sda_beep_files[] = { + SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep, + store_beep, BEEP_ENABLE, 46), + SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep, + store_beep, BEEP_ENABLE, 47), +}; + /* * Driver interface */ @@ -1859,6 +1963,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, if (!(data->has_in & (1 << i))) continue; for (j = 0; j < ARRAY_SIZE(w83795_in[0]); j++) { + if (j == 4 && !data->enable_beep) + continue; err = fn(dev, &w83795_in[i][j].dev_attr); if (err) return err; @@ -1869,18 +1975,37 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, if (!(data->has_fan & (1 << i))) continue; for (j = 0; j < ARRAY_SIZE(w83795_fan[0]); j++) { + if (j == 3 && !data->enable_beep) + continue; err = fn(dev, &w83795_fan[i][j].dev_attr); if (err) return err; } } + for (i = 0; i < ARRAY_SIZE(w83795_tss); i++) { + j = w83795_tss_useful(data, i); + if (!j) + continue; + err = fn(dev, &w83795_tss[i].dev_attr); + if (err) + return err; + } + for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { err = fn(dev, &sda_single_files[i].dev_attr); if (err) return err; } + if (data->enable_beep) { + for (i = 0; i < ARRAY_SIZE(sda_beep_files); i++) { + err = fn(dev, &sda_beep_files[i].dev_attr); + if (err) + return err; + } + } + #ifdef CONFIG_SENSORS_W83795_FANCTRL for (i = 0; i < data->has_pwm; i++) { for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) { @@ -1899,6 +2024,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, #else for (j = 0; j < 8; j++) { #endif + if (j == 7 && !data->enable_beep) + continue; err = fn(dev, &w83795_temp[i][j].dev_attr); if (err) return err; @@ -1910,6 +2037,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, if (!(data->has_dts & (1 << i))) continue; for (j = 0; j < ARRAY_SIZE(w83795_dts[0]); j++) { + if (j == 7 && !data->enable_beep) + continue; err = fn(dev, &w83795_dts[i][j].dev_attr); if (err) return err; @@ -2049,6 +2178,18 @@ static int w83795_probe(struct i2c_client *client, else data->has_pwm = 2; + /* Check if BEEP pin is available */ + if (data->chip_type == w83795g) { + /* The W83795G has a dedicated BEEP pin */ + data->enable_beep = 1; + } else { + /* The W83795ADG has a shared pin for OVT# and BEEP, so you + * can't have both */ + tmp = w83795_read(client, W83795_REG_OVT_CFG); + if ((tmp & OVT_CFG_SEL) == 0) + data->enable_beep = 1; + } + err = w83795_handle_files(dev, device_create_file); if (err) goto exit_remove; |