diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-07 18:05:39 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-07 18:05:39 -0700 |
commit | a06dee41a31bff488a261dfc542776ffd2f24ff1 (patch) | |
tree | 4930b7698d5d238f159c2d6628c7c1c62765b42b /drivers | |
parent | b588e2bbd7b872c9cdf635fe0f04840534e72443 (diff) | |
parent | 816d8c6a2580562698cf0fa0b9e5b4dd570e636e (diff) |
Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
* 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
hwmon: (it87) Support for 16-bit fan reading in it8705 >= rev 0x03
hwmon: (it87) Support for 16-bit fan reading in it8712 >= rev 0x07
hwmon: (hwmon-vid) Add 6-bit vid codes for AMD NPT 0Fh cpus
hwmon: (hwmon-vid) Trivial format multi-line comments per CodingStyle
hwmon: ad7414 driver
hwmon: (thmc50) Add support for critical temperature limits
hwmon: (adm9240) Remove EXPERIMENTAL dependency
hwmon: (w83627hf) Drop reset module parameter
hwmon: (w83627hf) Add pwm_enable sysfs interface
hwmon: (w83791d) Use fan divisor bits from vbat register
hwmon: (f71882fg) Delete needless forward declarations
hwmon: (dme1737) Add support for the SMSC SCH5027
hwmon: (dme1737) Skip detection if forced
hwmon: (dme1737) Cleanups
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/Kconfig | 16 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/ad7414.c | 268 | ||||
-rw-r--r-- | drivers/hwmon/dme1737.c | 292 | ||||
-rw-r--r-- | drivers/hwmon/f71882fg.c | 6 | ||||
-rw-r--r-- | drivers/hwmon/hwmon-vid.c | 144 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 45 | ||||
-rw-r--r-- | drivers/hwmon/thmc50.c | 28 | ||||
-rw-r--r-- | drivers/hwmon/w83627hf.c | 101 | ||||
-rw-r--r-- | drivers/hwmon/w83791d.c | 24 |
10 files changed, 687 insertions, 238 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c882fd05cf2..bf4ebfb86fa 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -57,6 +57,16 @@ config SENSORS_ABITUGURU3 This driver can also be built as a module. If so, the module will be called abituguru3. +config SENSORS_AD7414 + tristate "Analog Devices AD7414" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Analog Devices + AD7414 temperature monitoring chip. + + This driver can also be built as a module. If so, the module + will be called ad7414. + config SENSORS_AD7418 tristate "Analog Devices AD7416, AD7417 and AD7418" depends on I2C && EXPERIMENTAL @@ -124,7 +134,7 @@ config SENSORS_ADM1031 config SENSORS_ADM9240 tristate "Analog Devices ADM9240 and compatibles" - depends on I2C && EXPERIMENTAL + depends on I2C select HWMON_VID help If you say yes here you get support for Analog Devices ADM9240, @@ -575,8 +585,8 @@ config SENSORS_DME1737 select HWMON_VID help If you say yes here you get support for the hardware monitoring - and fan control features of the SMSC DME1737 (and compatibles - like the Asus A8000) and SCH311x Super-I/O chips. + and fan control features of the SMSC DME1737, SCH311x, SCH5027, and + Asus A8000 Super-I/O chips. This driver can also be built as a module. If so, the module will be called dme1737. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d098677e08d..7943e5cefb0 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o +obj-$(CONFIG_SENSORS_AD7414) += ad7414.o obj-$(CONFIG_SENSORS_AD7418) += ad7418.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c new file mode 100644 index 00000000000..ce8d94fbfd7 --- /dev/null +++ b/drivers/hwmon/ad7414.c @@ -0,0 +1,268 @@ +/* + * An hwmon driver for the Analog Devices AD7414 + * + * Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering + * + * Copyright (c) 2008 PIKA Technologies + * Sean MacLennan <smaclennan@pikatech.com> + * + * Copyright (c) 2008 Spansion Inc. + * Frank Edelhaeuser <frank.edelhaeuser at spansion.com> + * (converted to "new style" I2C driver model, removed checkpatch.pl warnings) + * + * Based on ad7418.c + * Copyright 2006 Tower Technologies, Alessandro Zummo <a.zummo at towertech.it> + * + * 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. + */ + +#include <linux/module.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> + + +/* AD7414 registers */ +#define AD7414_REG_TEMP 0x00 +#define AD7414_REG_CONF 0x01 +#define AD7414_REG_T_HIGH 0x02 +#define AD7414_REG_T_LOW 0x03 + +static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW }; + +struct ad7414_data { + struct device *hwmon_dev; + struct mutex lock; /* atomic read data updates */ + char valid; /* !=0 if following fields are valid */ + unsigned long next_update; /* In jiffies */ + s16 temp_input; /* Register values */ + s8 temps[ARRAY_SIZE(AD7414_REG_LIMIT)]; +}; + +/* REG: (0.25C/bit, two's complement) << 6 */ +static inline int ad7414_temp_from_reg(s16 reg) +{ + /* use integer division instead of equivalent right shift to + * guarantee arithmetic shift and preserve the sign + */ + return ((int)reg / 64) * 250; +} + +static inline int ad7414_read(struct i2c_client *client, u8 reg) +{ + if (reg == AD7414_REG_TEMP) { + int value = i2c_smbus_read_word_data(client, reg); + return (value < 0) ? value : swab16(value); + } else + return i2c_smbus_read_byte_data(client, reg); +} + +static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +struct ad7414_data *ad7414_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ad7414_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->next_update) || !data->valid) { + int value, i; + + dev_dbg(&client->dev, "starting ad7414 update\n"); + + value = ad7414_read(client, AD7414_REG_TEMP); + if (value < 0) + dev_dbg(&client->dev, "AD7414_REG_TEMP err %d\n", + value); + else + data->temp_input = value; + + for (i = 0; i < ARRAY_SIZE(AD7414_REG_LIMIT); ++i) { + value = ad7414_read(client, AD7414_REG_LIMIT[i]); + if (value < 0) + dev_dbg(&client->dev, "AD7414 reg %d err %d\n", + AD7414_REG_LIMIT[i], value); + else + data->temps[i] = value; + } + + data->next_update = jiffies + HZ + HZ / 2; + data->valid = 1; + } + + mutex_unlock(&data->lock); + + return data; +} + +static ssize_t show_temp_input(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7414_data *data = ad7414_update_device(dev); + return sprintf(buf, "%d\n", ad7414_temp_from_reg(data->temp_input)); +} +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); + +static ssize_t show_max_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct ad7414_data *data = ad7414_update_device(dev); + return sprintf(buf, "%d\n", data->temps[index] * 1000); +} + +static ssize_t set_max_min(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ad7414_data *data = i2c_get_clientdata(client); + int index = to_sensor_dev_attr(attr)->index; + u8 reg = AD7414_REG_LIMIT[index]; + long temp = simple_strtol(buf, NULL, 10); + + temp = SENSORS_LIMIT(temp, -40000, 85000); + temp = (temp + (temp < 0 ? -500 : 500)) / 1000; + + mutex_lock(&data->lock); + data->temps[index] = temp; + ad7414_write(client, reg, temp); + mutex_unlock(&data->lock); + return count; +} + +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, + show_max_min, set_max_min, 0); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, + show_max_min, set_max_min, 1); + +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct ad7414_data *data = ad7414_update_device(dev); + int value = (data->temp_input >> bitnr) & 1; + return sprintf(buf, "%d\n", value); +} + +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 4); + +static struct attribute *ad7414_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group ad7414_group = { + .attrs = ad7414_attributes, +}; + +static int ad7414_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ad7414_data *data; + int conf; + int err = 0; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_READ_WORD_DATA)) + goto exit; + + data = kzalloc(sizeof(struct ad7414_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "chip found\n"); + + /* Make sure the chip is powered up. */ + conf = i2c_smbus_read_byte_data(client, AD7414_REG_CONF); + if (conf < 0) + dev_warn(&client->dev, + "ad7414_probe unable to read config register.\n"); + else { + conf &= ~(1 << 7); + i2c_smbus_write_byte_data(client, AD7414_REG_CONF, conf); + } + + /* Register sysfs hooks */ + err = sysfs_create_group(&client->dev.kobj, &ad7414_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; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ad7414_group); +exit_free: + kfree(data); +exit: + return err; +} + +static int __devexit ad7414_remove(struct i2c_client *client) +{ + struct ad7414_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ad7414_group); + kfree(data); + return 0; +} + +static const struct i2c_device_id ad7414_id[] = { + { "ad7414", 0 }, + {} +}; + +static struct i2c_driver ad7414_driver = { + .driver = { + .name = "ad7414", + }, + .probe = ad7414_probe, + .remove = __devexit_p(ad7414_remove), + .id_table = ad7414_id, +}; + +static int __init ad7414_init(void) +{ + return i2c_add_driver(&ad7414_driver); +} +module_init(ad7414_init); + +static void __exit ad7414_exit(void) +{ + i2c_del_driver(&ad7414_driver); +} +module_exit(ad7414_exit); + +MODULE_AUTHOR("Stefan Roese <sr at denx.de>, " + "Frank Edelhaeuser <frank.edelhaeuser at spansion.com>"); + +MODULE_DESCRIPTION("AD7414 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 5e2cf0aef48..cdb8311e4ef 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -1,11 +1,11 @@ /* - * dme1737.c - Driver for the SMSC DME1737, Asus A8000, and SMSC SCH311x - * Super-I/O chips integrated hardware monitoring features. - * Copyright (c) 2007 Juerg Haefliger <juergh@gmail.com> + * dme1737.c - Driver for the SMSC DME1737, Asus A8000, SMSC SCH311x and + * SCH5027 Super-I/O chips integrated hardware monitoring features. + * Copyright (c) 2007, 2008 Juerg Haefliger <juergh@gmail.com> * * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access - * the chip registers if a DME1737 (or A8000) is found and the ISA bus if a - * SCH311x chip is found. Both types of chips have very similar hardware + * the chip registers if a DME1737, A8000, or SCH5027 is found and the ISA bus + * if a SCH311x chip is found. Both types of chips have very similar hardware * monitoring capabilities but differ in the way they can be accessed. * * This program is free software; you can redistribute it and/or modify @@ -57,7 +57,10 @@ MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC " static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; /* Insmod parameters */ -I2C_CLIENT_INSMOD_1(dme1737); +I2C_CLIENT_INSMOD_2(dme1737, sch5027); + +/* ISA chip types */ +enum isa_chips { sch311x = sch5027 + 1 }; /* --------------------------------------------------------------------- * Registers @@ -163,6 +166,7 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; #define DME1737_VERSTEP 0x88 #define DME1737_VERSTEP_MASK 0xf8 #define SCH311X_DEVICE 0x8c +#define SCH5027_VERSTEP 0x69 /* Length of ISA address segment */ #define DME1737_EXTENT 2 @@ -182,6 +186,7 @@ struct dme1737_data { unsigned long last_update; /* in jiffies */ unsigned long last_vbat; /* in jiffies */ enum chips type; + const int *in_nominal; /* pointer to IN_NOMINAL array */ u8 vid; u8 pwm_rr_en; @@ -220,23 +225,23 @@ static const int IN_NOMINAL_DME1737[] = {5000, 2250, 3300, 5000, 12000, 3300, 3300}; static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300, 3300}; -#define IN_NOMINAL(ix, type) (((type) == dme1737) ? \ - IN_NOMINAL_DME1737[(ix)] : \ - IN_NOMINAL_SCH311x[(ix)]) +static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, + 3300}; +#define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ + (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ + IN_NOMINAL_DME1737) /* Voltage input * Voltage inputs have 16 bits resolution, limit values have 8 bits * resolution. */ -static inline int IN_FROM_REG(int reg, int ix, int res, int type) +static inline int IN_FROM_REG(int reg, int nominal, int res) { - return (reg * IN_NOMINAL(ix, type) + (3 << (res - 3))) / - (3 << (res - 2)); + return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2)); } -static inline int IN_TO_REG(int val, int ix, int type) +static inline int IN_TO_REG(int val, int nominal) { - return SENSORS_LIMIT((val * 192 + IN_NOMINAL(ix, type) / 2) / - IN_NOMINAL(ix, type), 0, 255); + return SENSORS_LIMIT((val * 192 + nominal / 2) / nominal, 0, 255); } /* Temperature input @@ -565,7 +570,10 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) /* Sample register contents every 1 sec */ if (time_after(jiffies, data->last_update + HZ) || !data->valid) { - data->vid = dme1737_read(client, DME1737_REG_VID) & 0x3f; + if (data->type != sch5027) { + data->vid = dme1737_read(client, DME1737_REG_VID) & + 0x3f; + } /* In (voltage) registers */ for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { @@ -593,8 +601,10 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) DME1737_REG_TEMP_MIN(ix)); data->temp_max[ix] = dme1737_read(client, DME1737_REG_TEMP_MAX(ix)); - data->temp_offset[ix] = dme1737_read(client, - DME1737_REG_TEMP_OFFSET(ix)); + if (data->type != sch5027) { + data->temp_offset[ix] = dme1737_read(client, + DME1737_REG_TEMP_OFFSET(ix)); + } } /* In and temp LSB registers @@ -669,9 +679,11 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) data->zone_abs[ix] = dme1737_read(client, DME1737_REG_ZONE_ABS(ix)); } - for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { - data->zone_hyst[ix] = dme1737_read(client, + if (data->type != sch5027) { + for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { + data->zone_hyst[ix] = dme1737_read(client, DME1737_REG_ZONE_HYST(ix)); + } } /* Alarm registers */ @@ -735,13 +747,13 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, switch (fn) { case SYS_IN_INPUT: - res = IN_FROM_REG(data->in[ix], ix, 16, data->type); + res = IN_FROM_REG(data->in[ix], data->in_nominal[ix], 16); break; case SYS_IN_MIN: - res = IN_FROM_REG(data->in_min[ix], ix, 8, data->type); + res = IN_FROM_REG(data->in_min[ix], data->in_nominal[ix], 8); break; case SYS_IN_MAX: - res = IN_FROM_REG(data->in_max[ix], ix, 8, data->type); + res = IN_FROM_REG(data->in_max[ix], data->in_nominal[ix], 8); break; case SYS_IN_ALARM: res = (data->alarms >> DME1737_BIT_ALARM_IN[ix]) & 0x01; @@ -768,12 +780,12 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); switch (fn) { case SYS_IN_MIN: - data->in_min[ix] = IN_TO_REG(val, ix, data->type); + data->in_min[ix] = IN_TO_REG(val, data->in_nominal[ix]); dme1737_write(client, DME1737_REG_IN_MIN(ix), data->in_min[ix]); break; case SYS_IN_MAX: - data->in_max[ix] = IN_TO_REG(val, ix, data->type); + data->in_max[ix] = IN_TO_REG(val, data->in_nominal[ix]); dme1737_write(client, DME1737_REG_IN_MAX(ix), data->in_max[ix]); break; @@ -1166,7 +1178,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", res); } -static struct attribute *dme1737_attr_pwm[]; +static struct attribute *dme1737_pwm_chmod_attr[]; static void dme1737_chmod_file(struct device*, struct attribute*, mode_t); static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, @@ -1230,7 +1242,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, switch (val) { case 0: /* Change permissions of pwm[ix] to read-only */ - dme1737_chmod_file(dev, dme1737_attr_pwm[ix], + dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix], S_IRUGO); /* Turn fan fully on */ data->pwm_config[ix] = PWM_EN_TO_REG(0, @@ -1245,12 +1257,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); /* Change permissions of pwm[ix] to read-writeable */ - dme1737_chmod_file(dev, dme1737_attr_pwm[ix], + dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix], S_IRUGO | S_IWUSR); break; case 2: /* Change permissions of pwm[ix] to read-only */ - dme1737_chmod_file(dev, dme1737_attr_pwm[ix], + dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix], S_IRUGO); /* Turn on auto mode using the saved zone channel * assignment */ @@ -1570,88 +1582,98 @@ static struct attribute *dme1737_attr[] ={ &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_alarm.dev_attr.attr, &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp1_offset.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_alarm.dev_attr.attr, &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_alarm.dev_attr.attr, &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, /* Zones */ - &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_zone1_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr, + NULL +}; + +static const struct attribute_group dme1737_group = { + .attrs = dme1737_attr, +}; + +/* The following struct holds misc attributes, which are not available in all + * chips. Their creation depends on the chip type which is determined during + * module load. */ +static struct attribute *dme1737_misc_attr[] = { + /* Temperatures */ + &sensor_dev_attr_temp1_offset.dev_attr.attr, + &sensor_dev_attr_temp2_offset.dev_attr.attr, + &sensor_dev_attr_temp3_offset.dev_attr.attr, + /* Zones */ + &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr, + &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr, + &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr, /* Misc */ &dev_attr_vrm.attr, &dev_attr_cpu0_vid.attr, NULL }; -static const struct attribute_group dme1737_group = { - .attrs = dme1737_attr, +static const struct attribute_group dme1737_misc_group = { + .attrs = dme1737_misc_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. */ -static struct attribute *dme1737_attr_pwm1[] = { +static struct attribute *dme1737_pwm1_attr[] = { &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm1_freq.dev_attr.attr, &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr, &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm2[] = { +static struct attribute *dme1737_pwm2_attr[] = { &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_pwm2_freq.dev_attr.attr, &sensor_dev_attr_pwm2_enable.dev_attr.attr, &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr, &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm3[] = { +static struct attribute *dme1737_pwm3_attr[] = { &sensor_dev_attr_pwm3.dev_attr.attr, &sensor_dev_attr_pwm3_freq.dev_attr.attr, &sensor_dev_attr_pwm3_enable.dev_attr.attr, &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr, &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm5[] = { +static struct attribute *dme1737_pwm5_attr[] = { &sensor_dev_attr_pwm5.dev_attr.attr, &sensor_dev_attr_pwm5_freq.dev_attr.attr, &sensor_dev_attr_pwm5_enable.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm6[] = { +static struct attribute *dme1737_pwm6_attr[] = { &sensor_dev_attr_pwm6.dev_attr.attr, &sensor_dev_attr_pwm6_freq.dev_attr.attr, &sensor_dev_attr_pwm6_enable.dev_attr.attr, @@ -1659,53 +1681,62 @@ static struct attribute *dme1737_attr_pwm6[] = { }; static const struct attribute_group dme1737_pwm_group[] = { - { .attrs = dme1737_attr_pwm1 }, - { .attrs = dme1737_attr_pwm2 }, - { .attrs = dme1737_attr_pwm3 }, + { .attrs = dme1737_pwm1_attr }, + { .attrs = dme1737_pwm2_attr }, + { .attrs = dme1737_pwm3_attr }, { .attrs = NULL }, - { .attrs = dme1737_attr_pwm5 }, - { .attrs = dme1737_attr_pwm6 }, + { .attrs = dme1737_pwm5_attr }, + { .attrs = dme1737_pwm6_attr }, +}; + +/* The following struct holds misc PWM attributes, which are not available in + * all chips. Their creation depends on the chip type which is determined + * during module load. */ +static struct attribute *dme1737_pwm_misc_attr[] = { + &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, }; /* The following structs hold the fan attributes, some of which are optional. * Their creation depends on the chip configuration which is determined during * module load. */ -static struct attribute *dme1737_attr_fan1[] = { +static struct attribute *dme1737_fan1_attr[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan1_type.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_fan2[] = { +static struct attribute *dme1737_fan2_attr[] = { &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_alarm.dev_attr.attr, &sensor_dev_attr_fan2_type.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_fan3[] = { +static struct attribute *dme1737_fan3_attr[] = { &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan3_min.dev_attr.attr, &sensor_dev_attr_fan3_alarm.dev_attr.attr, &sensor_dev_attr_fan3_type.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_fan4[] = { +static struct attribute *dme1737_fan4_attr[] = { &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan4_min.dev_attr.attr, &sensor_dev_attr_fan4_alarm.dev_attr.attr, &sensor_dev_attr_fan4_type.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_fan5[] = { +static struct attribute *dme1737_fan5_attr[] = { &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan5_min.dev_attr.attr, &sensor_dev_attr_fan5_alarm.dev_attr.attr, &sensor_dev_attr_fan5_max.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_fan6[] = { +static struct attribute *dme1737_fan6_attr[] = { &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan6_min.dev_attr.attr, &sensor_dev_attr_fan6_alarm.dev_attr.attr, @@ -1714,94 +1745,83 @@ static struct attribute *dme1737_attr_fan6[] = { }; static const struct attribute_group dme1737_fan_group[] = { - { .attrs = dme1737_attr_fan1 }, - { .attrs = dme1737_attr_fan2 }, - { .attrs = dme1737_attr_fan3 }, - { .attrs = dme1737_attr_fan4 }, - { .attrs = dme1737_attr_fan5 }, - { .attrs = dme1737_attr_fan6 }, + { .attrs = dme1737_fan1_attr }, + { .attrs = dme1737_fan2_attr }, + { .attrs = dme1737_fan3_attr }, + { .attrs = dme1737_fan4_attr }, + { .attrs = dme1737_fan5_attr }, + { .attrs = dme1737_fan6_attr }, }; -/* The permissions of all of the following attributes are changed to read- +/* The permissions of the following zone attributes are changed to read- * writeable if the chip is *not* locked. Otherwise they stay read-only. */ -static struct attribute *dme1737_attr_lock[] = { - /* Temperatures */ - &sensor_dev_attr_temp1_offset.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, - /* Zones */ - &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr, +static struct attribute *dme1737_zone_chmod_attr[] = { &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, NULL }; -static const struct attribute_group dme1737_lock_group = { - .attrs = dme1737_attr_lock, +static const struct attribute_group dme1737_zone_chmod_group = { + .attrs = dme1737_zone_chmod_attr, }; /* The permissions of the following PWM attributes are changed to read- * writeable if the chip is *not* locked and the respective PWM is available. * Otherwise they stay read-only. */ -static struct attribute *dme1737_attr_pwm1_lock[] = { +static struct attribute *dme1737_pwm1_chmod_attr[] = { &sensor_dev_attr_pwm1_freq.dev_attr.attr, &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr, &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm2_lock[] = { +static struct attribute *dme1737_pwm2_chmod_attr[] = { &sensor_dev_attr_pwm2_freq.dev_attr.attr, &sensor_dev_attr_pwm2_enable.dev_attr.attr, &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr, &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm3_lock[] = { +static struct attribute *dme1737_pwm3_chmod_attr[] = { &sensor_dev_attr_pwm3_freq.dev_attr.attr, &sensor_dev_attr_pwm3_enable.dev_attr.attr, &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr, &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm5_lock[] = { +static struct attribute *dme1737_pwm5_chmod_attr[] = { &sensor_dev_attr_pwm5.dev_attr.attr, &sensor_dev_attr_pwm5_freq.dev_attr.attr, NULL }; -static struct attribute *dme1737_attr_pwm6_lock[] = { +static struct attribute *dme1737_pwm6_chmod_attr[] = { &sensor_dev_attr_pwm6.dev_attr.attr, &sensor_dev_attr_pwm6_freq.dev_attr.attr, NULL }; -static const struct attribute_group dme1737_pwm_lock_group[] = { - { .attrs = dme1737_attr_pwm1_lock }, - { .attrs = dme1737_attr_pwm2_lock }, - { .attrs = dme1737_attr_pwm3_lock }, +static const struct attribute_group dme1737_pwm_chmod_group[] = { + { .attrs = dme1737_pwm1_chmod_attr }, + { .attrs = dme1737_pwm2_chmod_attr }, + { .attrs = dme1737_pwm3_chmod_attr }, { .attrs = NULL }, - { .attrs = dme1737_attr_pwm5_lock }, - { .attrs = dme1737_attr_pwm6_lock }, + { .attrs = dme1737_pwm5_chmod_attr }, + { .attrs = dme1737_pwm6_chmod_attr }, }; /* Pwm[1-3] are read-writeable if the associated pwm is in manual mode and the * chip is not locked. Otherwise they are read-only. */ -static struct attribute *dme1737_attr_pwm[] = { +static struct attribute *dme1737_pwm_chmod_attr[] = { &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_pwm3.dev_attr.attr, @@ -1875,9 +1895,17 @@ static void dme1737_remove_files(struct device *dev) if (data->has_pwm & (1 << ix)) { sysfs_remove_group(&dev->kobj, &dme1737_pwm_group[ix]); + if (data->type != sch5027 && ix < 3) { + sysfs_remove_file(&dev->kobj, + dme1737_pwm_misc_attr[ix]); + } } } + if (data->type != sch5027) { + sysfs_remove_group(&dev->kobj, &dme1737_misc_group); + } + sysfs_remove_group(&dev->kobj, &dme1737_group); if (!data->client.driver) { @@ -1901,6 +1929,13 @@ static int dme1737_create_files(struct device *dev) goto exit_remove; } + /* Create misc sysfs attributes */ + if ((data->type != sch5027) && + (err = sysfs_create_group(&dev->kobj, + &dme1737_misc_group))) { + goto exit_remove; + } + /* Create fan sysfs attributes */ for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { if (data->has_fan & (1 << ix)) { @@ -1918,6 +1953,11 @@ static int dme1737_create_files(struct device *dev) &dme1737_pwm_group[ix]))) { goto exit_remove; } + if (data->type != sch5027 && ix < 3 && + (err = sysfs_create_file(&dev->kobj, + dme1737_pwm_misc_attr[ix]))) { + goto exit_remove; + } } } @@ -1927,16 +1967,27 @@ static int dme1737_create_files(struct device *dev) dev_info(dev, "Device is locked. Some attributes " "will be read-only.\n"); } else { - /* Change permissions of standard attributes */ - dme1737_chmod_group(dev, &dme1737_lock_group, + /* Change permissions of zone sysfs attributes */ + dme1737_chmod_group(dev, &dme1737_zone_chmod_group, S_IRUGO | S_IWUSR); - /* Change permissions of PWM attributes */ - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_lock_group); ix++) { + /* Change permissions of misc sysfs attributes */ + if (data->type != sch5027) { + dme1737_chmod_group(dev, &dme1737_misc_group, + S_IRUGO | S_IWUSR); + } + + /* Change permissions of PWM sysfs attributes */ + for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_chmod_group); ix++) { if (data->has_pwm & (1 << ix)) { dme1737_chmod_group(dev, - &dme1737_pwm_lock_group[ix], + &dme1737_pwm_chmod_group[ix], + S_IRUGO | S_IWUSR); + if (data->type != sch5027 && ix < 3) { + dme1737_chmod_file(dev, + dme1737_pwm_misc_attr[ix], S_IRUGO | S_IWUSR); + } } } @@ -1945,7 +1996,7 @@ static int dme1737_create_files(struct device *dev) if ((data->has_pwm & (1 << ix)) && (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { dme1737_chmod_file(dev, - dme1737_attr_pwm[ix], + dme1737_pwm_chmod_attr[ix], S_IRUGO | S_IWUSR); } } @@ -1966,6 +2017,9 @@ static int dme1737_init_device(struct device *dev) int ix; u8 reg; + /* Point to the right nominal voltages array */ + data->in_nominal = IN_NOMINAL(data->type); + data->config = dme1737_read(client, DME1737_REG_CONFIG); /* Inform if part is not monitoring/started */ if (!(data->config & 0x01)) { @@ -2076,7 +2130,9 @@ static int dme1737_init_device(struct device *dev) data->pwm_acz[2] = 4; /* pwm3 -&g |