From 7fce084a0b3e2bb8caef919f8f36065953655bb5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 3 Nov 2007 17:29:20 +0100 Subject: [PATCH 01/59] dmi: Let drivers walk the DMI table Let drivers walk the DMI table for their own needs. Some drivers need data stored in OEM-specific DMI records for proper operation. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/firmware/dmi_scan.c | 62 ++++++++++++++++++++++++++++--------- include/linux/dmi.h | 3 ++ 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index e0bade732376..1412d7bcdbd1 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -43,18 +43,12 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s) * We have to be cautious here. We have seen BIOSes with DMI pointers * pointing to completely the wrong place for example */ -static int __init dmi_table(u32 base, int len, int num, - void (*decode)(const struct dmi_header *)) +static void dmi_table(u8 *buf, int len, int num, + void (*decode)(const struct dmi_header *)) { - u8 *buf, *data; + u8 *data = buf; int i = 0; - buf = dmi_ioremap(base, len); - if (buf == NULL) - return -1; - - data = buf; - /* * Stop when we see all the items the table claimed to have * OR we run off the end of the table (also happens) @@ -75,7 +69,23 @@ static int __init dmi_table(u32 base, int len, int num, data += 2; i++; } - dmi_iounmap(buf, len); +} + +static u32 dmi_base; +static u16 dmi_len; +static u16 dmi_num; + +static int __init dmi_walk_early(void (*decode)(const struct dmi_header *)) +{ + u8 *buf; + + buf = dmi_ioremap(dmi_base, dmi_len); + if (buf == NULL) + return -1; + + dmi_table(buf, dmi_len, dmi_num, decode); + + dmi_iounmap(buf, dmi_len); return 0; } @@ -291,9 +301,9 @@ static int __init dmi_present(const char __iomem *p) memcpy_fromio(buf, p, 15); if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { - u16 num = (buf[13] << 8) | buf[12]; - u16 len = (buf[7] << 8) | buf[6]; - u32 base = (buf[11] << 24) | (buf[10] << 16) | + dmi_num = (buf[13] << 8) | buf[12]; + dmi_len = (buf[7] << 8) | buf[6]; + dmi_base = (buf[11] << 24) | (buf[10] << 16) | (buf[9] << 8) | buf[8]; /* @@ -305,7 +315,7 @@ static int __init dmi_present(const char __iomem *p) buf[14] >> 4, buf[14] & 0xF); else printk(KERN_INFO "DMI present.\n"); - if (dmi_table(base,len, num, dmi_decode) == 0) + if (dmi_walk_early(dmi_decode) == 0) return 0; } return 1; @@ -489,3 +499,27 @@ int dmi_get_year(int field) return year; } + +/** + * dmi_walk - Walk the DMI table and get called back for every record + * @decode: Callback function + * + * Returns -1 when the DMI table can't be reached, 0 on success. + */ +int dmi_walk(void (*decode)(const struct dmi_header *)) +{ + u8 *buf; + + if (!dmi_available) + return -1; + + buf = ioremap(dmi_base, dmi_len); + if (buf == NULL) + return -1; + + dmi_table(buf, dmi_len, dmi_num, decode); + + iounmap(buf); + return 0; +} +EXPORT_SYMBOL_GPL(dmi_walk); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index b1251b2af568..bbc9992ec374 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -79,6 +79,7 @@ extern void dmi_scan_machine(void); extern int dmi_get_year(int field); extern int dmi_name_in_vendors(const char *str); extern int dmi_available; +extern int dmi_walk(void (*decode)(const struct dmi_header *)); #else @@ -89,6 +90,8 @@ static inline const struct dmi_device * dmi_find_device(int type, const char *na static inline int dmi_get_year(int year) { return 0; } static inline int dmi_name_in_vendors(const char *s) { return 0; } #define dmi_available 0 +static inline int dmi_walk(void (*decode)(const struct dmi_header *)) + { return -1; } #endif From 6722feada7f6213ba06d510ef853e57ddcd59dae Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 7 Oct 2007 12:25:46 +0200 Subject: [PATCH 02/59] hwmon: (lm78/w83781d) Probe fewer I2C addresses We've never seen any device supported by the lm78 or w83781d driver at addresses 0x20-0x27, so let's stop probing these addresses. Extra probes cost time, and have potential for confusing or misdetecting other I2C devices. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/lm78 | 4 ++-- Documentation/hwmon/w83781d | 6 +++--- drivers/hwmon/lm78.c | 6 ++---- drivers/hwmon/w83781d.c | 7 +++---- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Documentation/hwmon/lm78 b/Documentation/hwmon/lm78 index dfc318a60fd4..60932e26abaa 100644 --- a/Documentation/hwmon/lm78 +++ b/Documentation/hwmon/lm78 @@ -4,12 +4,12 @@ Kernel driver lm78 Supported chips: * National Semiconductor LM78 / LM78-J Prefix: 'lm78' - Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports) + Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports) Datasheet: Publicly available at the National Semiconductor website http://www.national.com/ * National Semiconductor LM79 Prefix: 'lm79' - Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports) + Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports) Datasheet: Publicly available at the National Semiconductor website http://www.national.com/ diff --git a/Documentation/hwmon/w83781d b/Documentation/hwmon/w83781d index b1e9f80098ee..dbeadb269a69 100644 --- a/Documentation/hwmon/w83781d +++ b/Documentation/hwmon/w83781d @@ -4,11 +4,11 @@ Kernel driver w83781d Supported chips: * Winbond W83781D Prefix: 'w83781d' - Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports) + Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports) Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83781d.pdf * Winbond W83782D Prefix: 'w83782d' - Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports) + Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports) Datasheet: http://www.winbond.com/PDF/sheet/w83782d.pdf * Winbond W83783S Prefix: 'w83783s' @@ -16,7 +16,7 @@ Supported chips: Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83783s.pdf * Winbond W83627HF Prefix: 'w83627hf' - Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports) + Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports) Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf * Asus AS99127F Prefix: 'as99127f' diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 3f7055ee679f..934378eb4f8f 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -37,10 +37,8 @@ static struct platform_device *pdev; /* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, - 0x25, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, I2C_CLIENT_END }; static unsigned short isa_address = 0x290; /* Insmod parameters */ diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index e0fa7520400d..d38b9ede3abd 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -54,9 +54,8 @@ static struct platform_device *pdev; /* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, I2C_CLIENT_END }; static unsigned short isa_address = 0x290; /* Insmod parameters */ @@ -1270,7 +1269,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) kind = w83783s; else if (val1 == 0x21 && vendid == winbond) kind = w83627hf; - else if (val1 == 0x31 && address >= 0x28) + else if (val1 == 0x31) kind = as99127f; else { if (kind == 0) From 5aebefb08682ebd67ea0b902950d00169e1451cb Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Wed, 7 Nov 2007 13:28:59 +0100 Subject: [PATCH 03/59] hwmon: (w83793) remove duplicated defines Remove duplicated defines. Signed-off-by: Nicolas Kaiser Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83793.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 48599e1cc554..6b5c99c9e806 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -131,6 +131,7 @@ static u8 scale_in_add[] = { 0, 0, 0, 0, 0, 0, 0, 150, 150, 0 }; #define PWM_DUTY 0 #define PWM_START 1 #define PWM_NONSTOP 2 +#define PWM_STOP_TIME 3 #define W83793_REG_PWM(index, nr) (((nr) == 0 ? 0xb3 : \ (nr) == 1 ? 0x220 : 0x218) + (index)) @@ -407,10 +408,6 @@ store_fan_min(struct device *dev, struct device_attribute *attr, return count; } -#define PWM_DUTY 0 -#define PWM_START 1 -#define PWM_NONSTOP 2 -#define PWM_STOP_TIME 3 static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, char *buf) { From ce9c2f449b9e6b68d3a71ba146d64c44c8945d8d Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Tue, 6 Nov 2007 03:21:42 -0500 Subject: [PATCH 04/59] hwmon: (adt7470) Replace power-of-two test Since already supplies a power-of-two test, there's no point in having this source file redefine it again. Signed-off-by: Robert P. J. Day Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adt7470.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 9810aaa0489d..a2155605e318 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -114,8 +114,6 @@ I2C_CLIENT_INSMOD_1(adt7470); /* sleep 1s while gathering temperature data */ #define TEMP_COLLECTION_TIME 1000 -#define power_of_2(x) (((x) & ((x) - 1)) == 0) - /* datasheet says to divide this number by the fan reading to get fan rpm */ #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM @@ -677,7 +675,7 @@ static int cvt_auto_temp(int input) { if (input == ADT7470_PWM_ALL_TEMPS) return 0; - if (input < 1 || !power_of_2(input)) + if (input < 1 || !is_power_of_2(input)) return -EINVAL; return ilog2(input) + 1; } From 85f03bccd6e0e2ac6ccf017d4bcd5d74bb87a671 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Fri, 23 Nov 2007 09:31:52 +0800 Subject: [PATCH 05/59] hwmon: Add support for Winbond W83L786NG/NR Signed-off-by: Kevin Lo Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/w83l786ng | 54 +++ drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/w83l786ng.c | 821 ++++++++++++++++++++++++++++++++++ 4 files changed, 886 insertions(+) create mode 100644 Documentation/hwmon/w83l786ng create mode 100644 drivers/hwmon/w83l786ng.c diff --git a/Documentation/hwmon/w83l786ng b/Documentation/hwmon/w83l786ng new file mode 100644 index 000000000000..d8f55d7fff10 --- /dev/null +++ b/Documentation/hwmon/w83l786ng @@ -0,0 +1,54 @@ +Kernel driver w83l786ng +===================== + +Supported chips: + * Winbond W83L786NG/W83L786NR + Prefix: 'w83l786ng' + Addresses scanned: I2C 0x2e - 0x2f + Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83L786NRNG09.pdf + +Author: Kevin Lo + + +Module Parameters +----------------- + +* reset boolean + (default 0) + Use 'reset=1' to reset the chip (via index 0x40, bit 7). The default + behavior is no chip reset to preserve BIOS settings + + +Description +----------- + +This driver implements support for Winbond W83L786NG/W83L786NR chips. + +The driver implements two temperature sensors, two fan rotation speed +sensors, and three voltage sensors. + +Temperatures are measured in degrees Celsius and measurement resolution is 1 +degC for temp1 and temp2. + +Fan rotation speeds are reported in RPM (rotations per minute). Fan readings +readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 +or 128 for fan 1/2) to give the readings more range or accuracy. + +Voltage sensors (also known as IN sensors) report their values in millivolts. +An alarm is triggered if the voltage has crossed a programmable minimum +or maximum limit. + +/sys files +---------- + +pwm[1-2] - this file stores PWM duty cycle or DC value (fan speed) in range: + 0 (stop) to 255 (full) +pwm[1-2]_enable - this file controls mode of fan/temperature control: + * 0 Manual Mode + * 1 Thermal Cruise + * 2 Smart Fan II + * 4 FAN_SET +pwm[1-2]_mode - Select PWM of DC mode + * 0 DC + * 1 PWM +tolerance[1-2] - Value in degrees of Celsius (degC) for +- T diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index a0445bea9f75..a2187df5cc78 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -683,6 +683,16 @@ config SENSORS_W83L785TS This driver can also be built as a module. If so, the module will be called w83l785ts. +config SENSORS_W83L786NG + tristate "Winbond W83L786NG, W83L786NR" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Winbond W83L786NG + and W83L786NR sensor chips. + + This driver can also be built as a module. If so, the module + will be called w83l786ng. + config SENSORS_W83627HF tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" select HWMON_VID diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 55595f6e1aa6..77a3e093c247 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_SENSORS_VT1211) += vt1211.o obj-$(CONFIG_SENSORS_VT8231) += vt8231.o obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o +obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c new file mode 100644 index 000000000000..1dbee4fa23ad --- /dev/null +++ b/drivers/hwmon/w83l786ng.c @@ -0,0 +1,821 @@ +/* + w83l786ng.c - Linux kernel driver for hardware monitoring + Copyright (c) 2007 Kevin Lo + + 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 - version 2. + + 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 Street, Fifth Floor, Boston, MA + 02110-1301 USA. +*/ + +/* + Supports following chips: + + Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2e, 0x2f, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(w83l786ng); + +static int reset; +module_param(reset, bool, 0); +MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); + +#define W83L786NG_REG_IN_MIN(nr) (0x2C + (nr) * 2) +#define W83L786NG_REG_IN_MAX(nr) (0x2B + (nr) * 2) +#define W83L786NG_REG_IN(nr) ((nr) + 0x20) + +#define W83L786NG_REG_FAN(nr) ((nr) + 0x28) +#define W83L786NG_REG_FAN_MIN(nr) ((nr) + 0x3B) + +#define W83L786NG_REG_CONFIG 0x40 +#define W83L786NG_REG_ALARM1 0x41 +#define W83L786NG_REG_ALARM2 0x42 +#define W83L786NG_REG_GPIO_EN 0x47 +#define W83L786NG_REG_MAN_ID2 0x4C +#define W83L786NG_REG_MAN_ID1 0x4D +#define W83L786NG_REG_CHIP_ID 0x4E + +#define W83L786NG_REG_DIODE 0x53 +#define W83L786NG_REG_FAN_DIV 0x54 +#define W83L786NG_REG_FAN_CFG 0x80 + +#define W83L786NG_REG_TOLERANCE 0x8D + +static const u8 W83L786NG_REG_TEMP[2][3] = { + { 0x25, /* TEMP 0 in DataSheet */ + 0x35, /* TEMP 0 Over in DataSheet */ + 0x36 }, /* TEMP 0 Hyst in DataSheet */ + { 0x26, /* TEMP 1 in DataSheet */ + 0x37, /* TEMP 1 Over in DataSheet */ + 0x38 } /* TEMP 1 Hyst in DataSheet */ +}; + +static const u8 W83L786NG_PWM_MODE_SHIFT[] = {6, 7}; +static const u8 W83L786NG_PWM_ENABLE_SHIFT[] = {2, 4}; + +/* FAN Duty Cycle, be used to control */ +static const u8 W83L786NG_REG_PWM[] = {0x81, 0x87}; + + +static inline u8 +FAN_TO_REG(long rpm, int div) +{ + if (rpm == 0) + return 255; + rpm = SENSORS_LIMIT(rpm, 1, 1000000); + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); +} + +#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ + ((val) == 255 ? 0 : \ + 1350000 / ((val) * (div)))) + +/* for temp */ +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ + : (val)) / 1000, 0, 0xff)) +#define TEMP_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) + +/* The analog voltage inputs have 8mV LSB. Since the sysfs output is + in mV as would be measured on the chip input pin, need to just + multiply/divide by 8 to translate from/to register values. */ +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 4) / 8), 0, 255)) +#define IN_FROM_REG(val) ((val) * 8) + +#define DIV_FROM_REG(val) (1 << (val)) + +static inline u8 +DIV_TO_REG(long val) +{ + int i; + val = SENSORS_LIMIT(val, 1, 128) >> 1; + for (i = 0; i < 7; i++) { + if (val == 0) + break; + val >>= 1; + } + return ((u8) i); +} + +struct w83l786ng_data { + struct i2c_client client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long last_nonvolatile; /* In jiffies, last time we update the + nonvolatile registers */ + + u8 in[3]; + u8 in_max[3]; + u8 in_min[3]; + u8 fan[2]; + u8 fan_div[2]; + u8 fan_min[2]; + u8 temp_type[2]; + u8 temp[2][3]; + u8 pwm[2]; + u8 pwm_mode[2]; /* 0->DC variable voltage + 1->PWM variable duty cycle */ + + u8 pwm_enable[2]; /* 1->manual + 2->thermal cruise (also called SmartFan I) */ + u8 tolerance[2]; +}; + +static int w83l786ng_attach_adapter(struct i2c_adapter *adapter); +static int w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83l786ng_detach_client(struct i2c_client *client); +static void w83l786ng_init_client(struct i2c_client *client); +static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); + +static struct i2c_driver w83l786ng_driver = { + .driver = { + .name = "w83l786ng", + }, + .attach_adapter = w83l786ng_attach_adapter, + .detach_client = w83l786ng_detach_client, +}; + +static u8 +w83l786ng_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int +w83l786ng_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* following are the sysfs callback functions */ +#define show_in_reg(reg) \ +static ssize_t \ +show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + int nr = to_sensor_dev_attr(attr)->index; \ + struct w83l786ng_data *data = w83l786ng_update_device(dev); \ + return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \ +} + +show_in_reg(in) +show_in_reg(in_min) +show_in_reg(in_max) + +#define store_in_reg(REG, reg) \ +static ssize_t \ +store_in_##reg (struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + int nr = to_sensor_dev_attr(attr)->index; \ + struct i2c_client *client = to_i2c_client(dev); \ + struct w83l786ng_data *data = i2c_get_clientdata(client); \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = IN_TO_REG(val); \ + w83l786ng_write_value(client, W83L786NG_REG_IN_##REG(nr), \ + data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ + return count; \ +} + +store_in_reg(MIN, min) +store_in_reg(MAX, max) + +static struct sensor_device_attribute sda_in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), +}; + +static struct sensor_device_attribute sda_in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), +}; + +static struct sensor_device_attribute sda_in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), +}; + +#define show_fan_reg(reg) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + int nr = to_sensor_dev_attr(attr)->index; \ + struct w83l786ng_data *data = w83l786ng_update_device(dev); \ + return sprintf(buf,"%d\n", \ + FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \ +} + +show_fan_reg(fan); +show_fan_reg(fan_min); + +static ssize_t +store_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + u32 val; + + val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr), + data->fan_min[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct w83l786ng_data *data = w83l786ng_update_device(dev); + return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr])); +} + +/* Note: we save and restore the fan minimum here, because its value is + determined in part by the fan divisor. This follows the principle of + least surprise; the user doesn't expect the fan minimum to change just + because the divisor changed. */ +static ssize_t +store_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + + unsigned long min; + u8 tmp_fan_div; + u8 fan_div_reg; + u8 keep_mask = 0; + u8 new_shift = 0; + + /* Save fan_min */ + mutex_lock(&data->update_lock); + min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); + + data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10)); + + switch (nr) { + case 0: + keep_mask = 0xf8; + new_shift = 0; + break; + case 1: + keep_mask = 0x8f; + new_shift = 4; + break; + } + + fan_div_reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV) + & keep_mask; + + tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask; + + w83l786ng_write_value(client, W83L786NG_REG_FAN_DIV, + fan_div_reg | tmp_fan_div); + + /* Restore fan_min */ + data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr), + data->fan_min[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), +}; + +static struct sensor_device_attribute sda_fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, + store_fan_min, 0), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, + store_fan_min, 1), +}; + +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, + store_fan_div, 0), + SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, + store_fan_div, 1), +}; + + +/* read/write the temperature, includes measured value and limits */ + +static ssize_t +show_temp(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute_2 *sensor_attr = + to_sensor_dev_attr_2(attr); + int nr = sensor_attr->nr; + int index = sensor_attr->index; + struct w83l786ng_data *data = w83l786ng_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index])); +} + +static ssize_t +store_temp(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sensor_attr = + to_sensor_dev_attr_2(attr); + int nr = sensor_attr->nr; + int index = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + s32 val; + + val = simple_strtol(buf, NULL, 10); + mutex_lock(&data->update_lock); + data->temp[nr][index] = TEMP_TO_REG(val); + w83l786ng_write_value(client, W83L786NG_REG_TEMP[nr][index], + data->temp[nr][index]); + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute_2 sda_temp_input[] = { + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0), +}; + +static struct sensor_device_attribute_2 sda_temp_max[] = { + SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, + show_temp, store_temp, 0, 1), + SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, + show_temp, store_temp, 1, 1), +}; + +static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { + SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, + show_temp, store_temp, 0, 2), + SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, + show_temp, store_temp, 1, 2), +}; + +#define show_pwm_reg(reg) \ +static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct w83l786ng_data *data = w83l786ng_update_device(dev); \ + int nr = to_sensor_dev_attr(attr)->index; \ + return sprintf(buf, "%d\n", data->reg[nr]); \ +} + +show_pwm_reg(pwm_mode) +show_pwm_reg(pwm_enable) +show_pwm_reg(pwm) + +static ssize_t +store_pwm_mode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + u32 val = simple_strtoul(buf, NULL, 10); + u8 reg; + + if (val > 1) + return -EINVAL; + mutex_lock(&data->update_lock); + data->pwm_mode[nr] = val; + reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); + reg &= ~(1 << W83L786NG_PWM_MODE_SHIFT[nr]); + if (!val) + reg |= 1 << W83L786NG_PWM_MODE_SHIFT[nr]; + w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t +store_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255); + + mutex_lock(&data->update_lock); + data->pwm[nr] = val; + w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t +store_pwm_enable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + u32 val = simple_strtoul(buf, NULL, 10); + + u8 reg; + + if (!val || (val > 2)) /* only modes 1 and 2 are supported */ + return -EINVAL; + + mutex_lock(&data->update_lock); + reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); + data->pwm_enable[nr] = val; + reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]); + reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr]; + w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg); + mutex_unlock(&data->update_lock); + return count; +} + +static struct sensor_device_attribute sda_pwm[] = { + SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), + SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), +}; + +static struct sensor_device_attribute sda_pwm_mode[] = { + SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode, + store_pwm_mode, 0), + SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode, + store_pwm_mode, 1), +}; + +static struct sensor_device_attribute sda_pwm_enable[] = { + SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, + store_pwm_enable, 0), + SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, + store_pwm_enable, 1), +}; + +/* For Smart Fan I/Thermal Cruise and Smart Fan II */ +static ssize_t +show_tolerance(struct device *dev, struct device_attribute *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct w83l786ng_data *data = w83l786ng_update_device(dev); + return sprintf(buf, "%ld\n", (long)data->tolerance[nr]); +} + +static ssize_t +store_tolerance(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + u32 val; + u8 tol_tmp, tol_mask; + + val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + tol_mask = w83l786ng_read_value(client, + W83L786NG_REG_TOLERANCE) & ((nr == 1) ? 0x0f : 0xf0); + tol_tmp = SENSORS_LIMIT(val, 0, 15); + tol_tmp &= 0x0f; + data->tolerance[nr] = tol_tmp; + if (nr == 1) { + tol_tmp <<= 4; + } + + w83l786ng_write_value(client, W83L786NG_REG_TOLERANCE, + tol_mask | tol_tmp); + mutex_unlock(&data->update_lock); + return count; +} + +static struct sensor_device_attribute sda_tolerance[] = { + SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 0), + SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 1), +}; + + +#define IN_UNIT_ATTRS(X) \ + &sda_in_input[X].dev_attr.attr, \ + &sda_in_min[X].dev_attr.attr, \ + &sda_in_max[X].dev_attr.attr + +#define FAN_UNIT_ATTRS(X) \ + &sda_fan_input[X].dev_attr.attr, \ + &sda_fan_min[X].dev_attr.attr, \ + &sda_fan_div[X].dev_attr.attr + +#define TEMP_UNIT_ATTRS(X) \ + &sda_temp_input[X].dev_attr.attr, \ + &sda_temp_max[X].dev_attr.attr, \ + &sda_temp_max_hyst[X].dev_attr.attr + +#define PWM_UNIT_ATTRS(X) \ + &sda_pwm[X].dev_attr.attr, \ + &sda_pwm_mode[X].dev_attr.attr, \ + &sda_pwm_enable[X].dev_attr.attr + +#define TOLERANCE_UNIT_ATTRS(X) \ + &sda_tolerance[X].dev_attr.attr + +static struct attribute *w83l786ng_attributes[] = { + IN_UNIT_ATTRS(0), + IN_UNIT_ATTRS(1), + IN_UNIT_ATTRS(2), + FAN_UNIT_ATTRS(0), + FAN_UNIT_ATTRS(1), + TEMP_UNIT_ATTRS(0), + TEMP_UNIT_ATTRS(1), + PWM_UNIT_ATTRS(0), + PWM_UNIT_ATTRS(1), + TOLERANCE_UNIT_ATTRS(0), + TOLERANCE_UNIT_ATTRS(1), + NULL +}; + +static const struct attribute_group w83l786ng_group = { + .attrs = w83l786ng_attributes, +}; + +static int +w83l786ng_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83l786ng_detect); +} + +static int +w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct device *dev; + struct w83l786ng_data *data; + int i, err = 0; + u8 reg_tmp; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + goto exit; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83l786ng_{read,write}_value. */ + + if (!(data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83l786ng_driver; + + /* + * Now we do the remaining detection. A negative kind means that + * the driver was loaded with no force parameter (default), so we + * must both detect and identify the chip (actually there is only + * one possible kind of chip for now, W83L786NG). A zero kind means + * that the driver was loaded with the force parameter, the detection + * step shall be skipped. A positive kind means that the driver + * was loaded with the force parameter and a given kind of chip is + * requested, so both the detection and the identification steps + * are skipped. + */ + if (kind < 0) { /* detection */ + if (((w83l786ng_read_value(client, + W83L786NG_REG_CONFIG) & 0x80) != 0x00)) { + dev_dbg(&adapter->dev, + "W83L786NG detection failed at 0x%02x.\n", + address); + goto exit_free; + } + } + + if (kind <= 0) { /* identification */ + u16 man_id; + u8 chip_id; + + man_id = (w83l786ng_read_value(client, + W83L786NG_REG_MAN_ID1) << 8) + + w83l786ng_read_value(client, W83L786NG_REG_MAN_ID2); + chip_id = w83l786ng_read_value(client, W83L786NG_REG_CHIP_ID); + + if (man_id == 0x5CA3) { /* Winbond */ + if (chip_id == 0x80) { /* W83L786NG */ + kind = w83l786ng; + } + } + + if (kind <= 0) { /* identification failed */ + dev_info(&adapter->dev, + "Unsupported chip (man_id=0x%04X, " + "chip_id=0x%02X).\n", man_id, chip_id); + goto exit_free; + } + } + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "w83l786ng", I2C_NAME_SIZE); + mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + /* Initialize the chip */ + w83l786ng_init_client(client); + + /* A few vars need to be filled upon startup */ + for (i = 0; i < 2; i++) { + data->fan_min[i] = w83l786ng_read_value(client, + W83L786NG_REG_FAN_MIN(i)); + } + + /* Update the fan divisor */ + reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV); + data->fan_div[0] = reg_tmp & 0x07; + data->fan_div[1] = (reg_tmp >> 4) & 0x07; + + /* Register sysfs hooks */ + if ((err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group))) + goto exit_remove; + + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + return 0; + + /* Unregister sysfs hooks */ + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int +w83l786ng_detach_client(struct i2c_client *client) +{ + struct w83l786ng_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(data); + + return 0; +} + +static void +w83l786ng_init_client(struct i2c_client *client) +{ + u8 tmp; + + if (reset) + w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80); + + /* Start monitoring */ + tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG); + if (!(tmp & 0x01)) + w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01); +} + +static struct w83l786ng_data *w83l786ng_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83l786ng_data *data = i2c_get_clientdata(client); + int i, j; + u8 reg_tmp, pwmcfg; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + dev_dbg(&client->dev, "Updating w83l786ng data.\n"); + + /* Update the voltages measured value and limits */ + for (i = 0; i < 3; i++) { + data->in[i] = w83l786ng_read_value(client, + W83L786NG_REG_IN(i)); + data->in_min[i] = w83l786ng_read_value(client, + W83L786NG_REG_IN_MIN(i)); + data->in_max[i] = w83l786ng_read_value(client, + W83L786NG_REG_IN_MAX(i)); + } + + /* Update the fan counts and limits */ + for (i = 0; i < 2; i++) { + data->fan[i] = w83l786ng_read_value(client, + W83L786NG_REG_FAN(i)); + data->fan_min[i] = w83l786ng_read_value(client, + W83L786NG_REG_FAN_MIN(i)); + } + + /* Update the fan divisor */ + reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV); + data->fan_div[0] = reg_tmp & 0x07; + data->fan_div[1] = (reg_tmp >> 4) & 0x07; + + pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); + for (i = 0; i < 2; i++) { + data->pwm_mode[i] = + ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1) + ? 0 : 1; + data->pwm_enable[i] = + ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1; + data->pwm[i] = w83l786ng_read_value(client, + W83L786NG_REG_PWM[i]); + } + + + /* Update the temperature sensors */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + data->temp[i][j] = w83l786ng_read_value(client, + W83L786NG_REG_TEMP[i][j]); + } + } + + /* Update Smart Fan I/II tolerance */ + reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE); + data->tolerance[0] = reg_tmp & 0x0f; + data->tolerance[1] = (reg_tmp >> 4) & 0x0f; + + data->last_updated = jiffies; + data->valid = 1; + + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init +sensors_w83l786ng_init(void) +{ + return i2c_add_driver(&w83l786ng_driver); +} + +static void __exit +sensors_w83l786ng_exit(void) +{ + i2c_del_driver(&w83l786ng_driver); +} + +MODULE_AUTHOR("Kevin Lo"); +MODULE_DESCRIPTION("w83l786ng driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_w83l786ng_init); +module_exit(sensors_w83l786ng_exit); From c7fa373796ea685874ca9525eeb3d0d0951e511b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 9 Oct 2007 15:22:22 +0200 Subject: [PATCH 06/59] hwmon: (lm87) Add support for the Analog Devices ADM1024 It happens that the Analog Devices ADM1024 is fully compatible with the National Semiconductor LM87, so support for the former can easily be added to the lm87 driver. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/lm87 | 11 ++++++++--- drivers/hwmon/Kconfig | 4 ++-- drivers/hwmon/lm87.c | 25 +++++++++++++++++++------ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Documentation/hwmon/lm87 b/Documentation/hwmon/lm87 index c952c57f0e11..ec27aa1b94cb 100644 --- a/Documentation/hwmon/lm87 +++ b/Documentation/hwmon/lm87 @@ -4,8 +4,12 @@ Kernel driver lm87 Supported chips: * National Semiconductor LM87 Prefix: 'lm87' - Addresses scanned: I2C 0x2c - 0x2f + Addresses scanned: I2C 0x2c - 0x2e Datasheet: http://www.national.com/pf/LM/LM87.html + * Analog Devices ADM1024 + Prefix: 'adm1024' + Addresses scanned: I2C 0x2c - 0x2e + Datasheet: http://www.analog.com/en/prod/0,2877,ADM1024,00.html Authors: Frodo Looijaard , @@ -19,11 +23,12 @@ Authors: Description ----------- -This driver implements support for the National Semiconductor LM87. +This driver implements support for the National Semiconductor LM87 +and the Analog Devices ADM1024. The LM87 implements up to three temperature sensors, up to two fan rotation speed sensors, up to seven voltage sensors, alarms, and some -miscellaneous stuff. +miscellaneous stuff. The ADM1024 is fully compatible. Temperatures are measured in degrees Celsius. Each input has a high and low alarm settings. A high limit produces an alarm when the value diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index a2187df5cc78..af43d566d770 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -433,12 +433,12 @@ config SENSORS_LM85 will be called lm85. config SENSORS_LM87 - tristate "National Semiconductor LM87" + tristate "National Semiconductor LM87 and compatibles" depends on I2C select HWMON_VID help If you say yes here you get support for National Semiconductor LM87 - sensor chips. + and Analog Devices ADM1024 sensor chips. This driver can also be built as a module. If so, the module will be called lm87. diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 28cdff0c556b..3ab4c3f0efdd 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -5,7 +5,7 @@ * Philip Edelbrock * Stephen Rousset * Dan Eaton - * Copyright (C) 2004 Jean Delvare + * Copyright (C) 2004,2007 Jean Delvare * * Original port to Linux 2.6 by Jeff Oliver. * @@ -37,6 +37,11 @@ * instead. The LM87 is the only hardware monitoring chipset I know of * which uses amplitude modulation. Be careful when using this feature. * + * This driver also supports the ADM1024, a sensor chip made by Analog + * Devices. That chip is fully compatible with the LM87. Complete + * datasheet can be obtained from Analog's website at: + * http://www.analog.com/en/prod/0,2877,ADM1024,00.html + * * 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 @@ -74,7 +79,7 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; * Insmod parameters */ -I2C_CLIENT_INSMOD_1(lm87); +I2C_CLIENT_INSMOD_2(lm87, adm1024); /* * The LM87 registers @@ -662,6 +667,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) struct i2c_client *new_client; struct lm87_data *data; int err = 0; + static const char *names[] = { "lm87", "adm1024" }; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) goto exit; @@ -686,11 +692,18 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) /* Now, we do the remaining detection. */ if (kind < 0) { + u8 cid = lm87_read_value(new_client, LM87_REG_COMPANY_ID); u8 rev = lm87_read_value(new_client, LM87_REG_REVISION); - if (rev < 0x01 || rev > 0x08 - || (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80) - || lm87_read_value(new_client, LM87_REG_COMPANY_ID) != 0x02) { + if (cid == 0x02 /* National Semiconductor */ + && (rev >= 0x01 && rev <= 0x08)) + kind = lm87; + else if (cid == 0x41 /* Analog Devices */ + && (rev & 0xf0) == 0x10) + kind = adm1024; + + if (kind < 0 + || (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) { dev_dbg(&adapter->dev, "LM87 detection failed at 0x%02x.\n", address); @@ -699,7 +712,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) } /* We can fill in the remaining client fields */ - strlcpy(new_client->name, "lm87", I2C_NAME_SIZE); + strlcpy(new_client->name, names[kind - 1], I2C_NAME_SIZE); data->valid = 0; mutex_init(&data->update_lock); From d8543e7f30fe9306c8d5a16086bf75f71ab79acf Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 10 Oct 2007 21:11:01 +0200 Subject: [PATCH 07/59] hwmon: (adm1025) Use dynamic sysfs callbacks This lets us get rid of macro-generated functions and shrinks the driver size by about 30%. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1025.c | 289 +++++++++++++++++++++------------------- 1 file changed, 153 insertions(+), 136 deletions(-) diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 041ecb0bdf48..f0d833eb1f47 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -153,86 +154,96 @@ struct adm1025_data { * Sysfs stuff */ -#define show_in(offset) \ -static ssize_t show_in##offset(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct adm1025_data *data = adm1025_update_device(dev); \ - return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \ - in_scale[offset])); \ -} \ -static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct adm1025_data *data = adm1025_update_device(dev); \ - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \ - in_scale[offset])); \ -} \ -static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct adm1025_data *data = adm1025_update_device(dev); \ - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \ - in_scale[offset])); \ -} \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); -show_in(0); -show_in(1); -show_in(2); -show_in(3); -show_in(4); -show_in(5); +static ssize_t +show_in(struct device *dev, struct device_attribute *attr, char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct adm1025_data *data = adm1025_update_device(dev); + return sprintf(buf, "%u\n", IN_FROM_REG(data->in[index], + in_scale[index])); +} -#define show_temp(offset) \ -static ssize_t show_temp##offset(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct adm1025_data *data = adm1025_update_device(dev); \ - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \ -} \ -static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct adm1025_data *data = adm1025_update_device(dev); \ - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \ -} \ -static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct adm1025_data *data = adm1025_update_device(dev); \ - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \ -}\ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp##offset, NULL); -show_temp(1); -show_temp(2); +static ssize_t +show_in_min(struct device *dev, struct device_attribute *attr, char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct adm1025_data *data = adm1025_update_device(dev); + return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[index], + in_scale[index])); +} + +static ssize_t +show_in_max(struct device *dev, struct device_attribute *attr, char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct adm1025_data *data = adm1025_update_device(dev); + return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[index], + in_scale[index])); +} + +static ssize_t +show_temp(struct device *dev, struct device_attribute *attr, char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct adm1025_data *data = adm1025_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[index])); +} + +static ssize_t +show_temp_min(struct device *dev, struct device_attribute *attr, char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct adm1025_data *data = adm1025_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[index])); +} + +static ssize_t +show_temp_max(struct device *dev, struct device_attribute *attr, char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct adm1025_data *data = adm1025_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[index])); +} + +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct adm1025_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->in_min[index] = IN_TO_REG(val, in_scale[index]); + i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(index), + data->in_min[index]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct adm1025_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->in_max[index] = IN_TO_REG(val, in_scale[index]); + i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(index), + data->in_max[index]); + mutex_unlock(&data->update_lock); + return count; +} #define set_in(offset) \ -static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ - data->in_min[offset]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} \ -static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ - data->in_max[offset]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} \ -static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ - show_in##offset##_min, set_in##offset##_min); \ -static DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ - show_in##offset##_max, set_in##offset##_max); +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ + show_in_max, set_in_max, offset) set_in(0); set_in(1); set_in(2); @@ -240,39 +251,45 @@ set_in(3); set_in(4); set_in(5); +static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct adm1025_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->temp_min[index] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(index), + data->temp_min[index]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct adm1025_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->temp_max[index] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(index), + data->temp_max[index]); + mutex_unlock(&data->update_lock); + return count; +} + #define set_temp(offset) \ -static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - data->temp_min[offset-1] = TEMP_TO_REG(val); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ - data->temp_min[offset-1]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} \ -static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - data->temp_max[offset-1] = TEMP_TO_REG(val); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ - data->temp_max[offset-1]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} \ -static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ - show_temp##offset##_min, set_temp##offset##_min); \ -static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ - show_temp##offset##_max, set_temp##offset##_max); +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ + show_temp, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ + show_temp_min, set_temp_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ + show_temp_max, set_temp_max, offset - 1) set_temp(1); set_temp(2); @@ -316,27 +333,27 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter) } static struct attribute *adm1025_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - &dev_attr_in2_input.attr, - &dev_attr_in3_input.attr, - &dev_attr_in5_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in1_min.attr, - &dev_attr_in2_min.attr, - &dev_attr_in3_min.attr, - &dev_attr_in5_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_max.attr, - &dev_attr_in5_max.attr, - &dev_attr_temp1_input.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp2_min.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp2_max.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, @@ -348,9 +365,9 @@ static const struct attribute_group adm1025_group = { }; static struct attribute *adm1025_attributes_opt[] = { - &dev_attr_in4_input.attr, - &dev_attr_in4_min.attr, - &dev_attr_in4_max.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, NULL }; @@ -464,11 +481,11 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) /* Pin 11 is either in4 (+12V) or VID4 */ if (!(config & 0x20)) { if ((err = device_create_file(&new_client->dev, - &dev_attr_in4_input)) + &sensor_dev_attr_in4_input.dev_attr)) || (err = device_create_file(&new_client->dev, - &dev_attr_in4_min)) + &sensor_dev_attr_in4_min.dev_attr)) || (err = device_create_file(&new_client->dev, - &dev_attr_in4_max))) + &sensor_dev_attr_in4_max.dev_attr))) goto exit_remove; } From bb081300326335594c273107fcd4e5bdad765ae7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 10 Oct 2007 21:11:52 +0200 Subject: [PATCH 08/59] hwmon: (adm1025) Add individual alarm files The future libsensors needs these individual alarm and fault files. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1025.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index f0d833eb1f47..92aaa98c1497 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -300,6 +300,23 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t +show_alarm(struct device *dev, struct device_attribute *attr, char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct adm1025_data *data = adm1025_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 14); + static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1025_data *data = adm1025_update_device(dev); @@ -348,12 +365,20 @@ static struct attribute *adm1025_attributes[] = { &sensor_dev_attr_in2_max.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, @@ -368,6 +393,7 @@ static struct attribute *adm1025_attributes_opt[] = { &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, NULL }; @@ -485,7 +511,9 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr)) || (err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_max.dev_attr))) + &sensor_dev_attr_in4_max.dev_attr)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_in4_alarm.dev_attr))) goto exit_remove; } From 4e9527998f8673b1e3bb6f9645b9700e7973581e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 10 Oct 2007 21:14:11 +0200 Subject: [PATCH 09/59] hwmon: (adm1025) Various cleanups * Whitespace cleanups * Constify scaling constants * Fold long lines * Drop redundant initializations to 0 * Rename new_client to just client * Use sysfs_create_group() * Drop a useless comment Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1025.c | 80 +++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 92aaa98c1497..c7a365a9e405 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -75,7 +75,7 @@ I2C_CLIENT_INSMOD_2(adm1025, ne1619); */ #define ADM1025_REG_MAN_ID 0x3E -#define ADM1025_REG_CHIP_ID 0x3F +#define ADM1025_REG_CHIP_ID 0x3F #define ADM1025_REG_CONFIG 0x40 #define ADM1025_REG_STATUS1 0x41 #define ADM1025_REG_STATUS2 0x42 @@ -93,7 +93,7 @@ I2C_CLIENT_INSMOD_2(adm1025, ne1619); * The ADM1025 uses signed 8-bit values for temperatures. */ -static int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; +static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; #define IN_FROM_REG(reg,scale) (((reg) * (scale) + 96) / 192) #define IN_TO_REG(val,scale) ((val) <= 0 ? 0 : \ @@ -293,7 +293,8 @@ static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ set_temp(1); set_temp(2); -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t +show_alarms(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1025_data *data = adm1025_update_device(dev); return sprintf(buf, "%u\n", data->alarms); @@ -317,19 +318,22 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 5); static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 4); static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 14); -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t +show_vid(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1025_data *data = adm1025_update_device(dev); return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); } static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t +show_vrm(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1025_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->vrm); } -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1025_data *data = i2c_get_clientdata(client); @@ -389,7 +393,7 @@ static const struct attribute_group adm1025_group = { .attrs = adm1025_attributes, }; -static struct attribute *adm1025_attributes_opt[] = { +static struct attribute *adm1025_attributes_in4[] = { &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, @@ -397,8 +401,8 @@ static struct attribute *adm1025_attributes_opt[] = { NULL }; -static const struct attribute_group adm1025_group_opt = { - .attrs = adm1025_attributes_opt, +static const struct attribute_group adm1025_group_in4 = { + .attrs = adm1025_attributes_in4, }; /* @@ -407,7 +411,7 @@ static const struct attribute_group adm1025_group_opt = { */ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *new_client; + struct i2c_client *client; struct adm1025_data *data; int err = 0; const char *name = ""; @@ -421,14 +425,11 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) goto exit; } - /* The common I2C client data is placed right before the - ADM1025-specific data. */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &adm1025_driver; - new_client->flags = 0; + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1025_driver; /* * Now we do the remaining detection. A negative kind means that @@ -440,12 +441,12 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) * requested, so both the detection and the identification steps * are skipped. */ - config = i2c_smbus_read_byte_data(new_client, ADM1025_REG_CONFIG); + config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); if (kind < 0) { /* detection */ if ((config & 0x80) != 0x00 - || (i2c_smbus_read_byte_data(new_client, + || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) & 0xC0) != 0x00 - || (i2c_smbus_read_byte_data(new_client, + || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) & 0xBC) != 0x00) { dev_dbg(&adapter->dev, "ADM1025 detection failed at 0x%02x.\n", @@ -457,11 +458,9 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) if (kind <= 0) { /* identification */ u8 man_id, chip_id; - man_id = i2c_smbus_read_byte_data(new_client, - ADM1025_REG_MAN_ID); - chip_id = i2c_smbus_read_byte_data(new_client, - ADM1025_REG_CHIP_ID); - + man_id = i2c_smbus_read_byte_data(client, ADM1025_REG_MAN_ID); + chip_id = i2c_smbus_read_byte_data(client, ADM1025_REG_CHIP_ID); + if (man_id == 0x41) { /* Analog Devices */ if ((chip_id & 0xF0) == 0x20) { /* ADM1025/ADM1025A */ kind = adm1025; @@ -489,35 +488,28 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) } /* We can fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; + strlcpy(client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto exit_free; /* Initialize the ADM1025 chip */ - adm1025_init_client(new_client); + adm1025_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1025_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group))) goto exit_detach; /* Pin 11 is either in4 (+12V) or VID4 */ if (!(config & 0x20)) { - if ((err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_input.dev_attr)) - || (err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_min.dev_attr)) - || (err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_max.dev_attr)) - || (err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_alarm.dev_attr))) + if ((err = sysfs_create_group(&client->dev.kobj, + &adm1025_group_in4))) goto exit_remove; } - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exit_remove; @@ -526,10 +518,10 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_remove: - sysfs_remove_group(&new_client->dev.kobj, &adm1025_group); - sysfs_remove_group(&new_client->dev.kobj, &adm1025_group_opt); + sysfs_remove_group(&client->dev.kobj, &adm1025_group); + sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); exit_detach: - i2c_detach_client(new_client); + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -585,7 +577,7 @@ static int adm1025_detach_client(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1025_group); - sysfs_remove_group(&client->dev.kobj, &adm1025_group_opt); + sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); if ((err = i2c_detach_client(client))) return err; From 7dcf9a31ef50367e474e5e320e8ec5e0a8b9d2f0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 24 Nov 2007 17:45:09 -0500 Subject: [PATCH 10/59] hwmon: (fschmd) Discard non-ASCII characters Somehow non-ASCII characters managed to sneak into the fschmd driver. Kick them out. Signed-off-by: Jean Delvare Cc: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/fschmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index 63a4df0580db..d427ea5623fb 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -133,7 +133,7 @@ static const u8 FSCHMD_REG_TEMP_STATE[5][5] = { { 0x71, 0x81, 0x91 }, /* her */ { 0x71, 0xd1, 0x81, 0x91 }, /* scy */ { 0x71, 0x81, 0x91 }, /* hrc */ - { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */ + { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */ }; /* temperature high limit registers, FSC does not document these. Proven to be @@ -146,7 +146,7 @@ static const u8 FSCHMD_REG_TEMP_LIMIT[5][5] = { { 0x76, 0x86, 0x96 }, /* her */ { 0x76, 0xd6, 0x86, 0x96 }, /* scy */ { 0x76, 0x86, 0x96 }, /* hrc */ - { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */ + { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */ }; /* These were found through experimenting with an fscher, currently they are From a5955ed27497385cc491ecbe40af45951e830881 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 22 Oct 2007 17:45:08 +0200 Subject: [PATCH 11/59] hwmon: (gl518sm) Various cleanups * Drop history, it doesn't belong there * Drop unused struct member * Drop bogus struct member comment * Drop unused driver ID * Rename new_client to client * Drop redundant initializations to 0 * Drop useless cast * Drop trailing space * Fix comment * Drop duplicate comment Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl518sm.c | 49 ++++++++++++++++------------------------- include/linux/i2c-id.h | 1 - 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index bb58d9866a37..842252eccdaa 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -30,10 +30,6 @@ * We did not keep that part of the original driver in the Linux 2.6 * version, since it was making the driver significantly more complex * with no real benefit. - * - * History: - * 2004-01-28 Original port. (Hong-Gunn Chew) - * 2004-01-31 Code review and approval. (Jean Delvare) */ #include @@ -129,7 +125,6 @@ struct gl518_data { u8 voltage_in[4]; /* Register values; [0] = VDD */ u8 voltage_min[4]; /* Register values; [0] = VDD */ u8 voltage_max[4]; /* Register values; [0] = VDD */ - u8 iter_voltage_in[4]; /* Register values; [0] = VDD */ u8 fan_in[2]; u8 fan_min[2]; u8 fan_div[2]; /* Register encoding, shifted right */ @@ -138,7 +133,7 @@ struct gl518_data { u8 temp_max; /* Register values */ u8 temp_hyst; /* Register values */ u8 alarms; /* Register value */ - u8 alarm_mask; /* Register value */ + u8 alarm_mask; u8 beep_mask; /* Register value */ u8 beep_enable; /* Boolean */ }; @@ -156,7 +151,6 @@ static struct i2c_driver gl518_driver = { .driver = { .name = "gl518sm", }, - .id = I2C_DRIVERID_GL518, .attach_adapter = gl518_attach_adapter, .detach_client = gl518_detach_client, }; @@ -391,7 +385,7 @@ static int gl518_attach_adapter(struct i2c_adapter *adapter) static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) { int i; - struct i2c_client *new_client; + struct i2c_client *client; struct gl518_data *data; int err = 0; @@ -408,25 +402,24 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); + client = &data->client; + i2c_set_clientdata(client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &gl518_driver; - new_client->flags = 0; + client->addr = address; + client->adapter = adapter; + client->driver = &gl518_driver; /* Now, we do the remaining detection. */ if (kind < 0) { - if ((gl518_read_value(new_client, GL518_REG_CHIP_ID) != 0x80) - || (gl518_read_value(new_client, GL518_REG_CONF) & 0x80)) + if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80) + || (gl518_read_value(client, GL518_REG_CONF) & 0x80)) goto exit_free; } /* Determine the chip type. */ if (kind <= 0) { - i = gl518_read_value(new_client, GL518_REG_REVISION); + i = gl518_read_value(client, GL518_REG_REVISION); if (i == 0x00) { kind = gl518sm_r00; } else if (i == 0x80) { @@ -442,25 +435,24 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) } /* Fill in the remaining client fields */ - strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE); + strlcpy(client->name, "gl518sm", I2C_NAME_SIZE); data->type = kind; - data->valid = 0; mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto exit_free; /* Initialize the GL518SM chip */ data->alarm_mask = 0xff; data->voltage_in[0]=data->voltage_in[1]=data->voltage_in[2]=0; - gl518_init_client((struct i2c_client *) new_client); + gl518_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &gl518_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group))) goto exit_detach; - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; @@ -469,9 +461,9 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &gl518_group); + sysfs_remove_group(&client->dev.kobj, &gl518_group); exit_detach: - i2c_detach_client(new_client); + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -512,9 +504,9 @@ static int gl518_detach_client(struct i2c_client *client) return 0; } -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized GL518 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ + the SMBus standard. */ static int gl518_read_value(struct i2c_client *client, u8 reg) { if ((reg >= 0x07) && (reg <= 0x0c)) @@ -523,9 +515,6 @@ static int gl518_read_value(struct i2c_client *client, u8 reg) return i2c_smbus_read_byte_data(client, reg); } -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized - GL518 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value) { if ((reg >= 0x07) && (reg <= 0x0c)) diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index f922b060158b..d33e16a3f544 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -100,7 +100,6 @@ These were originally in sensors.h in the lm_sensors package */ #define I2C_DRIVERID_LM78 1002 #define I2C_DRIVERID_LM75 1003 -#define I2C_DRIVERID_GL518 1004 #define I2C_DRIVERID_EEPROM 1005 #define I2C_DRIVERID_W83781D 1006 #define I2C_DRIVERID_LM80 1007 From 5314f5c1abf03a56c6607ddef96b7a5607bee2f8 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 22 Oct 2007 17:46:17 +0200 Subject: [PATCH 12/59] hwmon: (gl518sm) Don't create sysfs files for missing features The early revisions of the GL518SM do not report voltage values for the first 3 voltage channels. We should not create sysfs attributes for these missing features. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl518sm.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 842252eccdaa..8287a3af6d79 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -336,9 +336,6 @@ static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO, show_beep_mask, set_beep_mask); static struct attribute *gl518_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - &dev_attr_in2_input.attr, &dev_attr_in3_input.attr, &dev_attr_in0_min.attr, &dev_attr_in1_min.attr, @@ -371,6 +368,17 @@ static const struct attribute_group gl518_group = { .attrs = gl518_attributes, }; +static struct attribute *gl518_attributes_r80[] = { + &dev_attr_in0_input.attr, + &dev_attr_in1_input.attr, + &dev_attr_in2_input.attr, + NULL +}; + +static const struct attribute_group gl518_group_r80 = { + .attrs = gl518_attributes_r80, +}; + /* * Real code */ @@ -445,12 +453,15 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) /* Initialize the GL518SM chip */ data->alarm_mask = 0xff; - data->voltage_in[0]=data->voltage_in[1]=data->voltage_in[2]=0; gl518_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group))) goto exit_detach; + if (data->type == gl518sm_r80) + if ((err = sysfs_create_group(&client->dev.kobj, + &gl518_group_r80))) + goto exit_remove_files; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -462,6 +473,8 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&client->dev.kobj, &gl518_group); + if (data->type == gl518sm_r80) + sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); exit_detach: i2c_detach_client(client); exit_free: @@ -496,6 +509,8 @@ static int gl518_detach_client(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &gl518_group); + if (data->type == gl518sm_r80) + sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); if ((err = i2c_detach_client(client))) return err; From 28292e79dcecac3688530a7f78d1930b78fac96b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 22 Oct 2007 17:46:42 +0200 Subject: [PATCH 13/59] hwmon: (gl518sm) Refactor fan functions This makes the code more readable and the binary smaller (by 5% or so). Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl518sm.c | 110 ++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 50 deletions(-) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 8287a3af6d79..ed901f96a04f 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -166,24 +167,10 @@ static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", type##_FROM_REG(data->value)); \ } -#define show_fan(suffix, value, index) \ -static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct gl518_data *data = gl518_update_device(dev); \ - return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[index], \ - DIV_FROM_REG(data->fan_div[index]))); \ -} - show(TEMP, temp_input1, temp_in); show(TEMP, temp_max1, temp_max); show(TEMP, temp_hyst1, temp_hyst); show(BOOL, fan_auto1, fan_auto1); -show_fan(fan_input1, fan_in, 0); -show_fan(fan_input2, fan_in, 1); -show_fan(fan_min1, fan_min, 0); -show_fan(fan_min2, fan_min, 1); -show(DIV, fan_div1, fan_div[0]); -show(DIV, fan_div2, fan_div[1]); show(VDD, in_input0, voltage_in[0]); show(IN, in_input1, voltage_in[1]); show(IN, in_input2, voltage_in[2]); @@ -200,6 +187,32 @@ show(RAW, alarms, alarms); show(BOOL, beep_enable, beep_enable); show(BEEP_MASK, beep_mask, beep_mask); +static ssize_t show_fan_input(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct gl518_data *data = gl518_update_device(dev); + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_in[nr], + DIV_FROM_REG(data->fan_div[nr]))); +} + +static ssize_t show_fan_min(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct gl518_data *data = gl518_update_device(dev); + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], + DIV_FROM_REG(data->fan_div[nr]))); +} + +static ssize_t show_fan_div(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct gl518_data *data = gl518_update_device(dev); + return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); +} + #define set(type, suffix, value, reg) \ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ size_t count) \ @@ -241,8 +254,6 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c set(TEMP, temp_max1, temp_max, GL518_REG_TEMP_MAX); set(TEMP, temp_hyst1, temp_hyst, GL518_REG_TEMP_HYST); set_bits(BOOL, fan_auto1, fan_auto1, GL518_REG_MISC, 0x08, 3); -set_bits(DIV, fan_div1, fan_div[0], GL518_REG_MISC, 0xc0, 6); -set_bits(DIV, fan_div2, fan_div[1], GL518_REG_MISC, 0x30, 4); set_low(VDD, in_min0, voltage_min[0], GL518_REG_VDD_LIMIT); set_low(IN, in_min1, voltage_min[1], GL518_REG_VIN1_LIMIT); set_low(IN, in_min2, voltage_min[2], GL518_REG_VIN2_LIMIT); @@ -254,25 +265,27 @@ set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT); set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2); set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM); -static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct gl518_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int regvalue; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); - data->fan_min[0] = FAN_TO_REG(val, - DIV_FROM_REG(data->fan_div[0])); - regvalue = (regvalue & 0x00ff) | (data->fan_min[0] << 8); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + regvalue = (regvalue & (0xff << (8 * nr))) + | (data->fan_min[nr] << (8 * (1 - nr))); gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue); data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); - if (data->fan_min[0] == 0) - data->alarm_mask &= ~0x20; + if (data->fan_min[nr] == 0) + data->alarm_mask &= ~(0x20 << nr); else - data->alarm_mask |= 0x20; + data->alarm_mask |= (0x20 << nr); data->beep_mask &= data->alarm_mask; gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); @@ -280,28 +293,21 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c return count; } -static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct gl518_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int regvalue; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); - regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); - data->fan_min[1] = FAN_TO_REG(val, - DIV_FROM_REG(data->fan_div[1])); - regvalue = (regvalue & 0xff00) | data->fan_min[1]; - gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue); - - data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); - if (data->fan_min[1] == 0) - data->alarm_mask &= ~0x40; - else - data->alarm_mask |= 0x40; - data->beep_mask &= data->alarm_mask; - gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - + regvalue = gl518_read_value(client, GL518_REG_MISC); + data->fan_div[nr] = DIV_TO_REG(val); + regvalue = (regvalue & ~(0xc0 >> (2 * nr))) + | (data->fan_div[nr] << (6 - 2 * nr)); + gl518_write_value(client, GL518_REG_MISC, regvalue); mutex_unlock(&data->update_lock); return count; } @@ -311,12 +317,16 @@ static DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1); static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO, show_temp_hyst1, set_temp_hyst1); static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1); -static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL); -static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL); -static DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, show_fan_min1, set_fan_min1); -static DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, show_fan_min2, set_fan_min2); -static DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, show_fan_div1, set_fan_div1); -static DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, show_fan_div2, set_fan_div2); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); +static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, + show_fan_min, set_fan_min, 0); +static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, + show_fan_min, set_fan_min, 1); +static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, + show_fan_div, set_fan_div, 0); +static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, + show_fan_div, set_fan_div, 1); static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL); static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL); static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL); @@ -347,12 +357,12 @@ static struct attribute *gl518_attributes[] = { &dev_attr_in3_max.attr, &dev_attr_fan1_auto.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan2_div.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, From da6848da293b88e5ac46f5ecc6ae41122d5f680b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 22 Oct 2007 17:47:16 +0200 Subject: [PATCH 14/59] hwmon: (gl518sm) Add individual alarm and beep files The new libsensors needs these. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl518sm.c | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index ed901f96a04f..535ad8776a68 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -345,6 +345,61 @@ static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO, static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO, show_beep_mask, set_beep_mask); +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct gl518_data *data = gl518_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} + +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6); + +static ssize_t show_beep(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct gl518_data *data = gl518_update_device(dev); + return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); +} + +static ssize_t set_beep(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct gl518_data *data = i2c_get_clientdata(client); + int bitnr = to_sensor_dev_attr(attr)->index; + unsigned long bit; + + bit = simple_strtoul(buf, NULL, 10); + if (bit & ~1) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); + if (bit) + data->beep_mask |= (1 << bitnr); + else + data->beep_mask &= ~(1 << bitnr); + gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); + mutex_unlock(&data->update_lock); + return count; +} + +static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 0); +static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 1); +static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 2); +static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 3); +static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 4); +static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 5); +static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 6); + static struct attribute *gl518_attributes[] = { &dev_attr_in3_input.attr, &dev_attr_in0_min.attr, @@ -355,6 +410,14 @@ static struct attribute *gl518_attributes[] = { &dev_attr_in1_max.attr, &dev_attr_in2_max.attr, &dev_attr_in3_max.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in0_beep.dev_attr.attr, + &sensor_dev_attr_in1_beep.dev_attr.attr, + &sensor_dev_attr_in2_beep.dev_attr.attr, + &sensor_dev_attr_in3_beep.dev_attr.attr, &dev_attr_fan1_auto.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, @@ -363,10 +426,16 @@ static struct attribute *gl518_attributes[] = { &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_beep.dev_attr.attr, + &sensor_dev_attr_fan2_beep.dev_attr.attr, &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, &dev_attr_temp1_max_hyst.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_beep.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_beep_enable.attr, From 21df67b191fd612fa28aedd39ec1414d8effc454 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 22 Oct 2007 17:47:58 +0200 Subject: [PATCH 15/59] hwmon: (gl518sm) Report error on invalid fan div value If the user attempts to write a fan clock divider not supported by the chip, an error should be returned. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl518sm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 535ad8776a68..c5255118bc16 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -107,7 +107,6 @@ static inline u8 FAN_TO_REG(long rpm, int div) #define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255)) #define VDD_FROM_REG(val) (((val)*95+2)/4) -#define DIV_TO_REG(val) ((val)==4?2:(val)==2?1:(val)==1?0:3) #define DIV_FROM_REG(val) (1 << (val)) #define BEEP_MASK_TO_REG(val) ((val) & 0x7f & data->alarm_mask) @@ -302,9 +301,20 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, int regvalue; unsigned long val = simple_strtoul(buf, NULL, 10); + switch (val) { + case 1: val = 0; break; + case 2: val = 1; break; + case 4: val = 2; break; + case 8: val = 3; break; + default: + dev_err(dev, "Invalid fan clock divider %lu, choose one " + "of 1, 2, 4 or 8\n", val); + return -EINVAL; + } + mutex_lock(&data->update_lock); regvalue = gl518_read_value(client, GL518_REG_MISC); - data->fan_div[nr] = DIV_TO_REG(val); + data->fan_div[nr] = val; regvalue = (regvalue & ~(0xc0 >> (2 * nr))) | (data->fan_div[nr] << (6 - 2 * nr)); gl518_write_value(client, GL518_REG_MISC, regvalue); From 72240307e988627df46553846936aa89a0f6a283 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 23 Oct 2007 14:02:24 +0200 Subject: [PATCH 16/59] hwmon: (gl518sm) Fix the reported fan speed The fan speeds reported by the gl518sm driver are twice as much as they should. It's currently reporting the number of pulses per minute, not rotations per minute, while typical fans emit two pulses per rotation. This explains why all reports with this driver had very high speed values (between 9000 to 12000 RPM). Odd that nobody ever actually complained about this bug. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl518sm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index c5255118bc16..3b1ac48fce23 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -96,10 +96,10 @@ static inline u8 FAN_TO_REG(long rpm, int div) long rpmdiv; if (rpm == 0) return 0; - rpmdiv = SENSORS_LIMIT(rpm, 1, 1920000) * div; - return SENSORS_LIMIT((960000 + rpmdiv / 2) / rpmdiv, 1, 255); + rpmdiv = SENSORS_LIMIT(rpm, 1, 960000) * div; + return SENSORS_LIMIT((480000 + rpmdiv / 2) / rpmdiv, 1, 255); } -#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (960000/((val)*(div)))) +#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val)*(div)))) #define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255)) #define IN_FROM_REG(val) ((val)*19) From e0ae87a49cf3e721313bf8942299f3f140c6963c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 25 Nov 2007 21:58:21 +0100 Subject: [PATCH 17/59] hwmon: (lm90) Use generic i2c reads during detection As indirectly reported by Olof Johansson, the lm90 driver uses a custom i2c read function even during detection, at which point we don't know yet what device we're talking with. It would make more sense to only use the generic i2c read function at this point, so that we don't log irrelevant errors on misdetection. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm90.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 960df9fa75af..116093d0eb3e 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -531,24 +531,24 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) kind = lm90; if (kind < 0) { /* detection and identification */ - u8 man_id, chip_id, reg_config1, reg_convrate; + int man_id, chip_id, reg_config1, reg_convrate; - if (lm90_read_reg(new_client, LM90_REG_R_MAN_ID, - &man_id) < 0 - || lm90_read_reg(new_client, LM90_REG_R_CHIP_ID, - &chip_id) < 0 - || lm90_read_reg(new_client, LM90_REG_R_CONFIG1, - ®_config1) < 0 - || lm90_read_reg(new_client, LM90_REG_R_CONVRATE, - ®_convrate) < 0) + if ((man_id = i2c_smbus_read_byte_data(new_client, + LM90_REG_R_MAN_ID)) < 0 + || (chip_id = i2c_smbus_read_byte_data(new_client, + LM90_REG_R_CHIP_ID)) < 0 + || (reg_config1 = i2c_smbus_read_byte_data(new_client, + LM90_REG_R_CONFIG1)) < 0 + || (reg_convrate = i2c_smbus_read_byte_data(new_client, + LM90_REG_R_CONVRATE)) < 0) goto exit_free; if ((address == 0x4C || address == 0x4D) && man_id == 0x01) { /* National Semiconductor */ - u8 reg_config2; + int reg_config2; - if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2, - ®_config2) < 0) + if ((reg_config2 = i2c_smbus_read_byte_data(new_client, + LM90_REG_R_CONFIG2)) < 0) goto exit_free; if ((reg_config1 & 0x2A) == 0x00 From f28dc2f78bbcbf07b8a084fcd89cf6b4256f0664 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 4 Nov 2007 23:44:23 +0100 Subject: [PATCH 18/59] hwmon: (gl520sm) Various cleanups * Drop trailing spaces * Drop unused driver ID * Drop stray backslashes in macros * Rename new_client to client * Drop redundant initializations to 0 Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl520sm.c | 63 ++++++++++++++++++++--------------------- include/linux/i2c-id.h | 1 - 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 2d39d8fc2389..4fdfe820294b 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -43,9 +43,9 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD_1(gl520sm); -/* Many GL520 constants specified below +/* Many GL520 constants specified below One of the inputs can be configured as either temp or voltage. -That's why _TEMP2 and _IN4 access the same register +That's why _TEMP2 and _IN4 access the same register */ /* The GL520 registers */ @@ -114,7 +114,6 @@ static struct i2c_driver gl520_driver = { .driver = { .name = "gl520sm", }, - .id = I2C_DRIVERID_GL520, .attach_adapter = gl520_attach_adapter, .detach_client = gl520_detach_client, }; @@ -194,7 +193,7 @@ sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT) #define sysfs_in(n) \ sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \ sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \ -sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \ +sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) #define sysfs_fan(n) \ sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \ @@ -202,7 +201,7 @@ sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \ sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV) #define sysfs_fan_off(n) \ -sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \ +sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) #define sysfs_temp(n) \ sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \ @@ -477,7 +476,7 @@ static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *dat static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) { u8 r = simple_strtoul(buf, NULL, 10); - + mutex_lock(&data->update_lock); r &= data->alarm_mask; data->beep_mask = r; @@ -553,7 +552,7 @@ static int gl520_attach_adapter(struct i2c_adapter *adapter) static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *new_client; + struct i2c_client *client; struct gl520_data *data; int err = 0; @@ -570,59 +569,57 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &gl520_driver; - new_client->flags = 0; + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &gl520_driver; /* Determine the chip type. */ if (kind < 0) { - if ((gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) || - ((gl520_read_value(new_client, GL520_REG_REVISION) & 0x7f) != 0x00) || - ((gl520_read_value(new_client, GL520_REG_CONF) & 0x80) != 0x00)) { - dev_dbg(&new_client->dev, "Unknown chip type, skipping\n"); + if ((gl520_read_value(client, GL520_REG_CHIP_ID) != 0x20) || + ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || + ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { + dev_dbg(&client->dev, "Unknown chip type, skipping\n"); goto exit_free; } } /* Fill in the remaining client fields */ - strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE); - data->valid = 0; + strlcpy(client->name, "gl520sm", I2C_NAME_SIZE); mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto exit_free; /* Initialize the GL520SM chip */ - gl520_init_client(new_client); + gl520_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &gl520_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group))) goto exit_detach; if (data->two_temps) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(&client->dev, &dev_attr_temp2_input)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(&client->dev, &dev_attr_temp2_max)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(&client->dev, &dev_attr_temp2_max_hyst))) goto exit_remove_files; } else { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(&client->dev, &dev_attr_in4_input)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(&client->dev, &dev_attr_in4_min)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(&client->dev, &dev_attr_in4_max))) goto exit_remove_files; } - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; @@ -631,10 +628,10 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &gl520_group); - sysfs_remove_group(&new_client->dev.kobj, &gl520_group_opt); + sysfs_remove_group(&client->dev.kobj, &gl520_group); + sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); exit_detach: - i2c_detach_client(new_client); + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -697,7 +694,7 @@ static int gl520_detach_client(struct i2c_client *client) } -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized GL520 uses a high-byte first convention */ static int gl520_read_value(struct i2c_client *client, u8 reg) { diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index d33e16a3f544..efc74c0fda56 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -109,7 +109,6 @@ #define I2C_DRIVERID_BT869 1013 #define I2C_DRIVERID_MAXILIFE 1014 #define I2C_DRIVERID_MATORB 1015 -#define I2C_DRIVERID_GL520 1016 #define I2C_DRIVERID_THMC50 1017 #define I2C_DRIVERID_ADM1025 1020 #define I2C_DRIVERID_LM87 1021 From 8b4b0ab41bb0a5e72b6fceb9a7aff303c88960b4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 4 Nov 2007 23:44:52 +0100 Subject: [PATCH 19/59] hwmon: (gl520sm) Put register addresses in arrays This allows for some code refactoring, making the binary slightly smaller. This is also required to use dynamic sysfs callbacks for voltage and temperature files. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl520sm.c | 102 +++++++++++++++------------------------- 1 file changed, 39 insertions(+), 63 deletions(-) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 4fdfe820294b..7c3b73a1623d 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -56,37 +56,14 @@ That's why _TEMP2 and _IN4 access the same register #define GL520_REG_VID_INPUT 0x02 -#define GL520_REG_IN0_INPUT 0x15 -#define GL520_REG_IN0_LIMIT 0x0c -#define GL520_REG_IN0_MIN GL520_REG_IN0_LIMIT -#define GL520_REG_IN0_MAX GL520_REG_IN0_LIMIT +static const u8 GL520_REG_IN_INPUT[] = { 0x15, 0x14, 0x13, 0x0d, 0x0e }; +static const u8 GL520_REG_IN_LIMIT[] = { 0x0c, 0x09, 0x0a, 0x0b }; +static const u8 GL520_REG_IN_MIN[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x18 }; +static const u8 GL520_REG_IN_MAX[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x17 }; -#define GL520_REG_IN1_INPUT 0x14 -#define GL520_REG_IN1_LIMIT 0x09 -#define GL520_REG_IN1_MIN GL520_REG_IN1_LIMIT -#define GL520_REG_IN1_MAX GL520_REG_IN1_LIMIT - -#define GL520_REG_IN2_INPUT 0x13 -#define GL520_REG_IN2_LIMIT 0x0a -#define GL520_REG_IN2_MIN GL520_REG_IN2_LIMIT -#define GL520_REG_IN2_MAX GL520_REG_IN2_LIMIT - -#define GL520_REG_IN3_INPUT 0x0d -#define GL520_REG_IN3_LIMIT 0x0b -#define GL520_REG_IN3_MIN GL520_REG_IN3_LIMIT -#define GL520_REG_IN3_MAX GL520_REG_IN3_LIMIT - -#define GL520_REG_IN4_INPUT 0x0e -#define GL520_REG_IN4_MAX 0x17 -#define GL520_REG_IN4_MIN 0x18 - -#define GL520_REG_TEMP1_INPUT 0x04 -#define GL520_REG_TEMP1_MAX 0x05 -#define GL520_REG_TEMP1_MAX_HYST 0x06 - -#define GL520_REG_TEMP2_INPUT 0x0e -#define GL520_REG_TEMP2_MAX 0x17 -#define GL520_REG_TEMP2_MAX_HYST 0x18 +static const u8 GL520_REG_TEMP_INPUT[] = { 0x04, 0x0e }; +static const u8 GL520_REG_TEMP_MAX[] = { 0x05, 0x17 }; +static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; #define GL520_REG_FAN_INPUT 0x07 #define GL520_REG_FAN_MIN 0x08 @@ -191,9 +168,9 @@ static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL); sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT) #define sysfs_in(n) \ -sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \ -sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \ -sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) +sysfs_ro_n(in, n, _input, GL520_REG_IN_INPUT[n]) \ +sysfs_rw_n(in, n, _min, GL520_REG_IN_MIN[n]) \ +sysfs_rw_n(in, n, _max, GL520_REG_IN_MAX[n]) #define sysfs_fan(n) \ sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \ @@ -204,9 +181,9 @@ sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV) sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) #define sysfs_temp(n) \ -sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \ -sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \ -sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST) +sysfs_ro_n(temp, n, _input, GL520_REG_TEMP_INPUT[(n) - 1]) \ +sysfs_rw_n(temp, n, _max, GL520_REG_TEMP_MAX[(n) - 1]) \ +sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP_MAX_HYST[(n) - 1]) #define sysfs_alarms() \ sysfs_ro(alarms, , GL520_REG_ALARMS) \ @@ -717,7 +694,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct gl520_data *data = i2c_get_clientdata(client); - int val; + int val, i; mutex_lock(&data->update_lock); @@ -729,18 +706,13 @@ static struct gl520_data *gl520_update_device(struct device *dev) data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); data->vid = gl520_read_value(client, GL520_REG_VID_INPUT) & 0x1f; - val = gl520_read_value(client, GL520_REG_IN0_LIMIT); - data->in_min[0] = val & 0xff; - data->in_max[0] = (val >> 8) & 0xff; - val = gl520_read_value(client, GL520_REG_IN1_LIMIT); - data->in_min[1] = val & 0xff; - data->in_max[1] = (val >> 8) & 0xff; - val = gl520_read_value(client, GL520_REG_IN2_LIMIT); - data->in_min[2] = val & 0xff; - data->in_max[2] = (val >> 8) & 0xff; - val = gl520_read_value(client, GL520_REG_IN3_LIMIT); - data->in_min[3] = val & 0xff; - data->in_max[3] = (val >> 8) & 0xff; + for (i = 0; i < 4; i++) { + data->in_input[i] = gl520_read_value(client, + GL520_REG_IN_INPUT[i]); + val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]); + data->in_min[i] = val & 0xff; + data->in_max[i] = (val >> 8) & 0xff; + } val = gl520_read_value(client, GL520_REG_FAN_INPUT); data->fan_input[0] = (val >> 8) & 0xff; @@ -750,9 +722,12 @@ static struct gl520_data *gl520_update_device(struct device *dev) data->fan_min[0] = (val >> 8) & 0xff; data->fan_min[1] = val & 0xff; - data->temp_input[0] = gl520_read_value(client, GL520_REG_TEMP1_INPUT); - data->temp_max[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX); - data->temp_max_hyst[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX_HYST); + data->temp_input[0] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[0]); + data->temp_max[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX[0]); + data->temp_max_hyst[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[0]); val = gl520_read_value(client, GL520_REG_FAN_DIV); data->fan_div[0] = (val >> 6) & 0x03; @@ -764,20 +739,21 @@ static struct gl520_data *gl520_update_device(struct device *dev) val = gl520_read_value(client, GL520_REG_CONF); data->beep_enable = !((val >> 2) & 1); - data->in_input[0] = gl520_read_value(client, GL520_REG_IN0_INPUT); - data->in_input[1] = gl520_read_value(client, GL520_REG_IN1_INPUT); - data->in_input[2] = gl520_read_value(client, GL520_REG_IN2_INPUT); - data->in_input[3] = gl520_read_value(client, GL520_REG_IN3_INPUT); - /* Temp1 and Vin4 are the same input */ if (data->two_temps) { - data->temp_input[1] = gl520_read_value(client, GL520_REG_TEMP2_INPUT); - data->temp_max[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX); - data->temp_max_hyst[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX_HYST); + data->temp_input[1] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[1]); + data->temp_max[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX[1]); + data->temp_max_hyst[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[1]); } else { - data->in_input[4] = gl520_read_value(client, GL520_REG_IN4_INPUT); - data->in_min[4] = gl520_read_value(client, GL520_REG_IN4_MIN); - data->in_max[4] = gl520_read_value(client, GL520_REG_IN4_MAX); + data->in_input[4] = gl520_read_value(client, + GL520_REG_IN_INPUT[4]); + data->in_min[4] = gl520_read_value(client, + GL520_REG_IN_MIN[4]); + data->in_max[4] = gl520_read_value(client, + GL520_REG_IN_MAX[4]); } data->last_updated = jiffies; From 86d47f127d740b891da29daff5799d91b6bd2e17 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 4 Nov 2007 23:45:14 +0100 Subject: [PATCH 20/59] hwmon: (gl520sm) De-macro the sysfs callbacks Use standard dynamic sysfs callbacks instead of macro-generated wrappers. This makes the code more readable, and the binary smaller (by about 11%). Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl520sm.c | 406 +++++++++++++++++++++++----------------- 1 file changed, 238 insertions(+), 168 deletions(-) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 7c3b73a1623d..40bfdc702dc3 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -126,93 +127,13 @@ struct gl520_data { * Sysfs stuff */ -#define sysfs_r(type, n, item, reg) \ -static ssize_t get_##type##item (struct gl520_data *, char *, int); \ -static ssize_t get_##type##n##item (struct device *, struct device_attribute *attr, char *); \ -static ssize_t get_##type##n##item (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct gl520_data *data = gl520_update_device(dev); \ - return get_##type##item(data, buf, (n)); \ -} - -#define sysfs_w(type, n, item, reg) \ -static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \ -static ssize_t set_##type##n##item (struct device *, struct device_attribute *attr, const char *, size_t); \ -static ssize_t set_##type##n##item (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct gl520_data *data = i2c_get_clientdata(client); \ - return set_##type##item(client, data, buf, count, (n), reg); \ -} - -#define sysfs_rw_n(type, n, item, reg) \ -sysfs_r(type, n, item, reg) \ -sysfs_w(type, n, item, reg) \ -static DEVICE_ATTR(type##n##item, S_IRUGO | S_IWUSR, get_##type##n##item, set_##type##n##item); - -#define sysfs_ro_n(type, n, item, reg) \ -sysfs_r(type, n, item, reg) \ -static DEVICE_ATTR(type##n##item, S_IRUGO, get_##type##n##item, NULL); - -#define sysfs_rw(type, item, reg) \ -sysfs_r(type, 0, item, reg) \ -sysfs_w(type, 0, item, reg) \ -static DEVICE_ATTR(type##item, S_IRUGO | S_IWUSR, get_##type##0##item, set_##type##0##item); - -#define sysfs_ro(type, item, reg) \ -sysfs_r(type, 0, item, reg) \ -static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL); - - -#define sysfs_vid(n) \ -sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT) - -#define sysfs_in(n) \ -sysfs_ro_n(in, n, _input, GL520_REG_IN_INPUT[n]) \ -sysfs_rw_n(in, n, _min, GL520_REG_IN_MIN[n]) \ -sysfs_rw_n(in, n, _max, GL520_REG_IN_MAX[n]) - -#define sysfs_fan(n) \ -sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \ -sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \ -sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV) - -#define sysfs_fan_off(n) \ -sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) - -#define sysfs_temp(n) \ -sysfs_ro_n(temp, n, _input, GL520_REG_TEMP_INPUT[(n) - 1]) \ -sysfs_rw_n(temp, n, _max, GL520_REG_TEMP_MAX[(n) - 1]) \ -sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP_MAX_HYST[(n) - 1]) - -#define sysfs_alarms() \ -sysfs_ro(alarms, , GL520_REG_ALARMS) \ -sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \ -sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK) - - -sysfs_vid(0) - -sysfs_in(0) -sysfs_in(1) -sysfs_in(2) -sysfs_in(3) -sysfs_in(4) - -sysfs_fan(1) -sysfs_fan(2) -sysfs_fan_off(1) - -sysfs_temp(1) -sysfs_temp(2) - -sysfs_alarms() - - -static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n) +static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); } +static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL); #define VDD_FROM_REG(val) (((val)*95+2)/4) #define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255)) @@ -220,8 +141,11 @@ static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n) #define IN_FROM_REG(val) ((val)*19) #define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255)) -static ssize_t get_in_input(struct gl520_data *data, char *buf, int n) +static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, + char *buf) { + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); u8 r = data->in_input[n]; if (n == 0) @@ -230,8 +154,11 @@ static ssize_t get_in_input(struct gl520_data *data, char *buf, int n) return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t get_in_min(struct gl520_data *data, char *buf, int n) +static ssize_t get_in_min(struct device *dev, struct device_attribute *attr, + char *buf) { + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); u8 r = data->in_min[n]; if (n == 0) @@ -240,8 +167,11 @@ static ssize_t get_in_min(struct gl520_data *data, char *buf, int n) return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t get_in_max(struct gl520_data *data, char *buf, int n) +static ssize_t get_in_max(struct device *dev, struct device_attribute *attr, + char *buf) { + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); u8 r = data->in_max[n]; if (n == 0) @@ -250,8 +180,12 @@ static ssize_t get_in_max(struct gl520_data *data, char *buf, int n) return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); u8 r; @@ -265,16 +199,22 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co data->in_min[n] = r; if (n < 4) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r); + gl520_write_value(client, GL520_REG_IN_MIN[n], + (gl520_read_value(client, GL520_REG_IN_MIN[n]) + & ~0xff) | r); else - gl520_write_value(client, reg, r); + gl520_write_value(client, GL520_REG_IN_MIN[n], r); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); u8 r; @@ -288,57 +228,109 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co data->in_max[n] = r; if (n < 4) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8)); + gl520_write_value(client, GL520_REG_IN_MAX[n], + (gl520_read_value(client, GL520_REG_IN_MAX[n]) + & ~0xff00) | (r << 8)); else - gl520_write_value(client, reg, r); + gl520_write_value(client, GL520_REG_IN_MAX[n], r); mutex_unlock(&data->update_lock); return count; } +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, get_in_input, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, get_in_input, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, get_in_input, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, get_in_input, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, get_in_input, NULL, 4); +static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 0); +static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 1); +static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 2); +static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 3); +static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 4); +static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 0); +static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 1); +static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 2); +static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 3); +static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 4); + #define DIV_FROM_REG(val) (1 << (val)) #define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div)))) #define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255)); -static ssize_t get_fan_input(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n - 1], data->fan_div[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n], + data->fan_div[n])); } -static ssize_t get_fan_min(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n - 1], data->fan_div[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n], + data->fan_div[n])); } -static ssize_t get_fan_div(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n])); } -static ssize_t get_fan_off(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_off(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->fan_off); } -static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; unsigned long v = simple_strtoul(buf, NULL, 10); u8 r; mutex_lock(&data->update_lock); - r = FAN_TO_REG(v, data->fan_div[n - 1]); - data->fan_min[n - 1] = r; + r = FAN_TO_REG(v, data->fan_div[n]); + data->fan_min[n] = r; - if (n == 1) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8)); + if (n == 0) + gl520_write_value(client, GL520_REG_FAN_MIN, + (gl520_read_value(client, GL520_REG_FAN_MIN) + & ~0xff00) | (r << 8)); else - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r); + gl520_write_value(client, GL520_REG_FAN_MIN, + (gl520_read_value(client, GL520_REG_FAN_MIN) + & ~0xff) | r); data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); - if (data->fan_min[n - 1] == 0) - data->alarm_mask &= (n == 1) ? ~0x20 : ~0x40; + if (data->fan_min[n] == 0) + data->alarm_mask &= (n == 0) ? ~0x20 : ~0x40; else - data->alarm_mask |= (n == 1) ? 0x20 : 0x40; + data->alarm_mask |= (n == 0) ? 0x20 : 0x40; data->beep_mask &= data->alarm_mask; gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); @@ -346,8 +338,12 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c return count; } -static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; unsigned long v = simple_strtoul(buf, NULL, 10); u8 r; @@ -362,133 +358,207 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c } mutex_lock(&data->update_lock); - data->fan_div[n - 1] = r; + data->fan_div[n] = r; - if (n == 1) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xc0) | (r << 6)); + if (n == 0) + gl520_write_value(client, GL520_REG_FAN_DIV, + (gl520_read_value(client, GL520_REG_FAN_DIV) + & ~0xc0) | (r << 6)); else - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4)); + gl520_write_value(client, GL520_REG_FAN_DIV, + (gl520_read_value(client, GL520_REG_FAN_DIV) + & ~0x30) | (r << 4)); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); u8 r = simple_strtoul(buf, NULL, 10)?1:0; mutex_lock(&data->update_lock); data->fan_off = r; - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2)); + gl520_write_value(client, GL520_REG_FAN_OFF, + (gl520_read_value(client, GL520_REG_FAN_OFF) + & ~0x0c) | (r << 2)); mutex_unlock(&data->update_lock); return count; } +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_input, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan_input, NULL, 1); +static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, + get_fan_min, set_fan_min, 0); +static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, + get_fan_min, set_fan_min, 1); +static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, + get_fan_div, set_fan_div, 0); +static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, + get_fan_div, set_fan_div, 1); +static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR, + get_fan_off, set_fan_off); + #define TEMP_FROM_REG(val) (((val) - 130) * 1000) #define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-500:(val)+500) / 1000)+130),0,255)) -static ssize_t get_temp_input(struct gl520_data *data, char *buf, int n) +static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n])); } -static ssize_t get_temp_max(struct gl520_data *data, char *buf, int n) +static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n])); } -static ssize_t get_temp_max_hyst(struct gl520_data *data, char *buf, int n) +static ssize_t get_temp_max_hyst(struct device *dev, struct device_attribute + *attr, char *buf) { - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n])); } -static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); - data->temp_max[n - 1] = TEMP_TO_REG(v); - gl520_write_value(client, reg, data->temp_max[n - 1]); + data->temp_max[n] = TEMP_TO_REG(v); + gl520_write_value(client, GL520_REG_TEMP_MAX[n], data->temp_max[n]); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); - data->temp_max_hyst[n - 1] = TEMP_TO_REG(v); - gl520_write_value(client, reg, data->temp_max_hyst[n - 1]); + data->temp_max_hyst[n] = TEMP_TO_REG(v); + gl520_write_value(client, GL520_REG_TEMP_MAX_HYST[n], + data->temp_max_hyst[n]); mutex_unlock(&data->update_lock); return count; } -static ssize_t get_alarms(struct gl520_data *data, char *buf, int n) +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_temp_input, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_temp_input, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, + get_temp_max, set_temp_max, 0); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, + get_temp_max, set_temp_max, 1); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, + get_temp_max_hyst, set_temp_max_hyst, 0); +static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, + get_temp_max_hyst, set_temp_max_hyst, 1); + +static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->alarms); } -static ssize_t get_beep_enable(struct gl520_data *data, char *buf, int n) +static ssize_t get_beep_enable(struct device *dev, struct device_attribute + *attr, char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->beep_enable); } -static ssize_t get_beep_mask(struct gl520_data *data, char *buf, int n) +static ssize_t get_beep_mask(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->beep_mask); } -static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_beep_enable(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); u8 r = simple_strtoul(buf, NULL, 10)?0:1; mutex_lock(&data->update_lock); data->beep_enable = !r; - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2)); + gl520_write_value(client, GL520_REG_BEEP_ENABLE, + (gl520_read_value(client, GL520_REG_BEEP_ENABLE) + & ~0x04) | (r << 2)); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); u8 r = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); r &= data->alarm_mask; data->beep_mask = r; - gl520_write_value(client, reg, r); + gl520_write_value(client, GL520_REG_BEEP_MASK, r); mutex_unlock(&data->update_lock); return count; } +static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); +static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, + get_beep_enable, set_beep_enable); +static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, + get_beep_mask, set_beep_mask); + static struct attribute *gl520_attributes[] = { &dev_attr_cpu0_vid.attr, - &dev_attr_in0_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_input.attr, - &dev_attr_in1_min.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_input.attr, - &dev_attr_in2_min.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_input.attr, - &dev_attr_in3_min.attr, - &dev_attr_in3_max.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan1_div.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, &dev_attr_fan1_off.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan2_div.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_beep_enable.attr, @@ -501,13 +571,13 @@ static const struct attribute_group gl520_group = { }; static struct attribute *gl520_attributes_opt[] = { - &dev_attr_in4_input.attr, - &dev_attr_in4_min.attr, - &dev_attr_in4_max.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp2_max_hyst.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, NULL }; @@ -579,19 +649,19 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) if (data->two_temps) { if ((err = device_create_file(&client->dev, - &dev_attr_temp2_input)) + &sensor_dev_attr_temp2_input.dev_attr)) || (err = device_create_file(&client->dev, - &dev_attr_temp2_max)) + &sensor_dev_attr_temp2_max.dev_attr)) || (err = device_create_file(&client->dev, - &dev_attr_temp2_max_hyst))) + &sensor_dev_attr_temp2_max_hyst.dev_attr))) goto exit_remove_files; } else { if ((err = device_create_file(&client->dev, - &dev_attr_in4_input)) + &sensor_dev_attr_in4_input.dev_attr)) || (err = device_create_file(&client->dev, - &dev_attr_in4_min)) + &sensor_dev_attr_in4_min.dev_attr)) || (err = device_create_file(&client->dev, - &dev_attr_in4_max))) + &sensor_dev_attr_in4_max.dev_attr))) goto exit_remove_files; } From e86a776093cffef993841ab7dbb4b1611ebf9686 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 4 Nov 2007 23:45:41 +0100 Subject: [PATCH 21/59] hwmon: (gl520sm) Add individual alarm and beep files libsensors 3.0 needs these. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/gl520sm.c | 91 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 40bfdc702dc3..03ecdc334764 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -532,33 +532,108 @@ static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, get_beep_mask, set_beep_mask); +static ssize_t get_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bit_nr = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", (data->alarms >> bit_nr) & 1); +} + +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, get_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, get_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, get_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, get_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, get_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, get_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, get_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, get_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, get_alarm, NULL, 7); + +static ssize_t get_beep(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1); +} + +static ssize_t set_beep(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int bitnr = to_sensor_dev_attr(attr)->index; + unsigned long bit; + + bit = simple_strtoul(buf, NULL, 10); + if (bit & ~1) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); + if (bit) + data->beep_mask |= (1 << bitnr); + else + data->beep_mask &= ~(1 << bitnr); + gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); + mutex_unlock(&data->update_lock); + return count; +} + +static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 0); +static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 1); +static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 2); +static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 3); +static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 4); +static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 5); +static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 6); +static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); +static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); + static struct attribute *gl520_attributes[] = { &dev_attr_cpu0_vid.attr, &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in0_beep.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in1_beep.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in2_beep.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in3_beep.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_beep.dev_attr.attr, &dev_attr_fan1_off.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_beep.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_beep.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_beep_enable.attr, @@ -574,10 +649,14 @@ static struct attribute *gl520_attributes_opt[] = { &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in4_beep.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_beep.dev_attr.attr, NULL }; @@ -653,7 +732,11 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr)) || (err = device_create_file(&client->dev, - &sensor_dev_attr_temp2_max_hyst.dev_attr))) + &sensor_dev_attr_temp2_max_hyst.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_temp2_alarm.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_temp2_beep.dev_attr))) goto exit_remove_files; } else { if ((err = device_create_file(&client->dev, @@ -661,7 +744,11 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&client->dev, &sensor_dev_attr_in4_min.dev_attr)) || (err = device_create_file(&client->dev, - &sensor_dev_attr_in4_max.dev_attr))) + &sensor_dev_attr_in4_max.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_in4_alarm.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_in4_beep.dev_attr))) goto exit_remove_files; } From ec1d86c457c0d1a530914290d0bbd3ecce022272 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 18 Nov 2007 23:46:10 +0100 Subject: [PATCH 22/59] hwmon: Update the lm-sensors website address It's about time to reflect the move of the lm-sensors project to lm-sensors.org. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/userspace-tools | 2 +- Documentation/hwmon/w83627hf | 3 +-- Documentation/i2c/busses/i2c-piix4 | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Documentation/hwmon/userspace-tools b/Documentation/hwmon/userspace-tools index 19900a8fe679..9865aeedc58f 100644 --- a/Documentation/hwmon/userspace-tools +++ b/Documentation/hwmon/userspace-tools @@ -14,7 +14,7 @@ Lm-sensors Core set of utilities that will allow you to obtain health information, setup monitoring limits etc. You can get them on their homepage -http://www.lm-sensors.nu/ or as a package from your Linux distribution. +http://www.lm-sensors.org/ or as a package from your Linux distribution. If from website: Get lm-sensors from project web site. Please note, you need only userspace diff --git a/Documentation/hwmon/w83627hf b/Documentation/hwmon/w83627hf index 792231921241..880a59f53da9 100644 --- a/Documentation/hwmon/w83627hf +++ b/Documentation/hwmon/w83627hf @@ -73,5 +73,4 @@ doesn't help, you may just ignore the bogus VID reading with no harm done. For further information on this driver see the w83781d driver documentation. -[1] http://www2.lm-sensors.nu/~lm78/cvs/browse.cgi/lm_sensors2/doc/vid - +[1] http://www.lm-sensors.org/browser/lm-sensors/trunk/doc/vid diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index cf6b6cb02aa1..ef1efa79b1df 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -95,4 +95,4 @@ of all affected systems, so the only safe solution was to prevent access to the SMBus on all IBM systems (detected using DMI data.) For additional information, read: -http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad +http://www.lm-sensors.org/browser/lm-sensors/trunk/README.thinkpad From b20ff13a6ad64f07ce78c75e6a335c185270d73c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 19 Nov 2007 17:48:07 -0800 Subject: [PATCH 23/59] hwmon: (vt8231) Add missing "space" Signed-off-by: Joe Perches Signed-off-by: Mark M. Hoffman --- drivers/hwmon/vt8231.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 2196a84603f5..f87661775fe0 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -504,7 +504,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: - dev_err(dev, "fan_div value %ld not supported." + dev_err(dev, "fan_div value %ld not supported. " "Choose one of 1, 2, 4 or 8!\n", val); mutex_unlock(&data->update_lock); return -EINVAL; From 67b671bceb4a8340a30929e9642620d99ed5ad76 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 6 Dec 2007 23:13:42 +0100 Subject: [PATCH 24/59] hwmon: Let the user override the detected Super-I/O device ID While it is possible to force SMBus-based hardware monitoring chip drivers to drive a not officially supported device, we do not have this possibility for Super-I/O-based drivers. That's unfortunate because sometimes newer chips are fully compatible and just forcing the driver to load would work. Instead of that we have to tell the users to recompile the kernel driver, which isn't an easy task for everyone. So, I propose that we add a module parameter to all Super-I/O based hardware monitoring drivers, letting advanced users force the driver to load on their machine. The user has to provide the device ID of a supposedly compatible device. This requires looking at the source code or a datasheet, so I am confident that users can't randomly force a driver without knowing what they are doing. Thus this should be relatively safe. As you can see from the code, the implementation is pretty simple and unintrusive. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/dme1737.c | 6 +++++- drivers/hwmon/f71805f.c | 6 +++++- drivers/hwmon/f71882fg.c | 6 +++++- drivers/hwmon/it87.c | 6 +++++- drivers/hwmon/pc87360.c | 6 +++++- drivers/hwmon/pc87427.c | 6 +++++- drivers/hwmon/smsc47b397.c | 6 +++++- drivers/hwmon/smsc47m1.c | 6 +++++- drivers/hwmon/vt1211.c | 8 +++++++- drivers/hwmon/w83627ehf.c | 11 +++++++++-- drivers/hwmon/w83627hf.c | 6 +++++- 11 files changed, 61 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index a878c98e252e..85064fb0b7c2 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -44,6 +44,10 @@ static int force_start; module_param(force_start, bool, 0); MODULE_PARM_DESC(force_start, "Force the chip to start monitoring inputs"); +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + /* Addresses to scan */ static unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; @@ -2191,7 +2195,7 @@ static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr) /* Check device ID * We currently know about SCH3112 (0x7c), SCH3114 (0x7d), and * SCH3116 (0x7f). */ - reg = dme1737_sio_inb(sio_cip, 0x20); + reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) { err = -ENODEV; goto exit; diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 5d9d5cc816a2..7a14a2dbb752 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -41,6 +41,10 @@ #include #include +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + static struct platform_device *pdev; #define DRVNAME "f71805f" @@ -1497,7 +1501,7 @@ static int __init f71805f_find(int sioaddr, unsigned short *address, if (devid != SIO_FINTEK_ID) goto exit; - devid = superio_inw(sioaddr, SIO_REG_DEVID); + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); switch (devid) { case SIO_F71805F_ID: sio_data->kind = f71805f; diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 6db74434a02e..cbeb4984b5c7 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -74,6 +74,10 @@ #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + static struct platform_device *f71882fg_pdev = NULL; /* Super-I/O Function prototypes */ @@ -843,7 +847,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address) goto exit; } - devid = superio_inw(sioaddr, SIO_REG_DEVID); + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); if (devid != SIO_F71882_ID) { printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); goto exit; diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index ad6c8a319903..0932fd53352a 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -52,6 +52,10 @@ enum chips { it87, it8712, it8716, it8718 }; +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + static struct platform_device *pdev; #define REG 0x2e /* The register to read/write */ @@ -906,7 +910,7 @@ static int __init it87_find(unsigned short *address, u16 chip_type; superio_enter(); - chip_type = superio_inw(DEVID); + chip_type = force_id ? force_id : superio_inw(DEVID); switch (chip_type) { case IT8705F_DEVID: diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 9d660133d517..9b462bb13fa3 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -59,6 +59,10 @@ MODULE_PARM_DESC(init, " 2: Forcibly enable all voltage and temperature channels, except in9\n" " 3: Forcibly enable all voltage and temperature channels, including in9"); +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + /* * Super-I/O registers and operations */ @@ -826,7 +830,7 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses /* No superio_enter */ /* Identify device */ - val = superio_inb(sioaddr, DEVID); + val = force_id ? force_id : superio_inb(sioaddr, DEVID); switch (val) { case 0xE1: /* PC87360 */ case 0xE8: /* PC87363 */ diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index d40509ad6ae6..7265f22ae5cd 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -34,6 +34,10 @@ #include #include +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + static struct platform_device *pdev; #define DRVNAME "pc87427" @@ -555,7 +559,7 @@ static int __init pc87427_find(int sioaddr, unsigned short *address) int i, err = 0; /* Identify device */ - val = superio_inb(sioaddr, SIOREG_DEVID); + val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID); if (val != 0xf2) { /* PC87427 */ err = -ENODEV; goto exit; diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 0b57d2ea2cf7..f61d8f4185b2 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -38,6 +38,10 @@ #include #include +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + static struct platform_device *pdev; #define DRVNAME "smsc47b397" @@ -333,7 +337,7 @@ static int __init smsc47b397_find(unsigned short *addr) u8 id, rev; superio_enter(); - id = superio_inb(SUPERIO_REG_DEVID); + id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) { superio_exit(); diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index a10a380868e2..0d7f0c4d06bb 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -39,6 +39,10 @@ #include #include +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + static struct platform_device *pdev; #define DRVNAME "smsc47m1" @@ -399,7 +403,7 @@ static int __init smsc47m1_find(unsigned short *addr, u8 val; superio_enter(); - val = superio_inb(SUPERIO_REG_DEVID); + val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); /* * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 7dfcc8dd316d..12b43590fa53 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -42,6 +42,10 @@ static int int_mode = -1; module_param(int_mode, int, 0); MODULE_PARM_DESC(int_mode, "Force the temperature interrupt mode"); +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + static struct platform_device *pdev; #define DRVNAME "vt1211" @@ -1280,10 +1284,12 @@ EXIT: static int __init vt1211_find(int sio_cip, unsigned short *address) { int err = -ENODEV; + int devid; superio_enter(sio_cip); - if (superio_inb(sio_cip, SIO_VT1211_DEVID) != SIO_VT1211_ID) { + devid = force_id ? force_id : superio_inb(sio_cip, SIO_VT1211_DEVID); + if (devid != SIO_VT1211_ID) { goto EXIT; } diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index d5aa25ce5dbd..699592855bd8 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -59,6 +59,10 @@ static const char * w83627ehf_device_names[] = { "w83627dhg", }; +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + #define DRVNAME "w83627ehf" /* @@ -1445,8 +1449,11 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, superio_enter(sioaddr); - val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) - | superio_inb(sioaddr, SIO_REG_DEVID + 1); + if (force_id) + val = force_id; + else + val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) + | superio_inb(sioaddr, SIO_REG_DEVID + 1); switch (val & SIO_ID_MASK) { case SIO_W83627EHF_ID: sio_data->kind = w83627ehf; diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 879d0a6544cc..181f4e8590b1 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -75,6 +75,10 @@ static int init = 1; module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + /* modified from kernel/include/traps.c */ static int REG; /* The register to read/write */ #define DEV 0x07 /* Register: Logical device select */ @@ -1014,7 +1018,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, VAL = sioaddr + 1; superio_enter(); - val= superio_inb(DEVID); + val = force_id ? force_id : superio_inb(DEVID); switch (val) { case W627_DEVID: sio_data->type = w83627hf; From 7845cd791d87b9d5e6171452143dbef15aba00dc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 20 Dec 2007 16:42:59 +0100 Subject: [PATCH 25/59] hwmon: (fschmd) Read voltage scaling factors from BIOS DMI This patch adds support to the fschmd driver for reading the voltage scaling factors from BIOS DMI tables, as specified in the Siemens datasheet. Signed-off-by: Hans de Goede Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/fschmd.c | 90 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index d427ea5623fb..b7c9eef0f928 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -41,6 +41,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; @@ -210,6 +211,13 @@ struct fschmd_data { u8 fan_ripple[6]; /* divider for rps */ }; +/* Global variables to hold information read from special DMI tables, which are + available on FSC machines with an fscher or later chip. */ +static int dmi_mult[3] = { 490, 200, 100 }; +static int dmi_offset[3] = { 0, 0, 0 }; +static int dmi_vref = -1; + + /* * Sysfs attr show / store functions */ @@ -221,8 +229,13 @@ static ssize_t show_in_value(struct device *dev, int index = to_sensor_dev_attr(devattr)->index; struct fschmd_data *data = fschmd_update_device(dev); - return sprintf(buf, "%d\n", (data->volt[index] * - max_reading[index] + 128) / 255); + /* fscher / fschrc - 1 as data->kind is an array index, not a chips */ + if (data->kind == (fscher - 1) || data->kind >= (fschrc - 1)) + return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref * + dmi_mult[index]) / 255 + dmi_offset[index]); + else + return sprintf(buf, "%d\n", (data->volt[index] * + max_reading[index] + 128) / 255); } @@ -525,6 +538,68 @@ static struct sensor_device_attribute fschmd_fan_attr[] = { * Real code */ +/* DMI decode routine to read voltage scaling factors from special DMI tables, + which are available on FSC machines with an fscher or later chip. */ +static void fschmd_dmi_decode(const struct dmi_header *header) +{ + int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0; + + /* dmi code ugliness, we get passed the address of the contents of + a complete DMI record, but in the form of a dmi_header pointer, in + reality this address holds header->length bytes of which the header + are the first 4 bytes */ + u8 *dmi_data = (u8 *)header; + + /* We are looking for OEM-specific type 185 */ + if (header->type != 185) + return; + + /* we are looking for what Siemens calls "subtype" 19, the subtype + is stored in byte 5 of the dmi block */ + if (header->length < 5 || dmi_data[4] != 19) + return; + + /* After the subtype comes 1 unknown byte and then blocks of 5 bytes, + consisting of what Siemens calls an "Entity" number, followed by + 2 16-bit words in LSB first order */ + for (i = 6; (i + 4) < header->length; i += 5) { + /* entity 1 - 3: voltage multiplier and offset */ + if (dmi_data[i] >= 1 && dmi_data[i] <= 3) { + /* Our in sensors order and the DMI order differ */ + const int shuffle[3] = { 1, 0, 2 }; + int in = shuffle[dmi_data[i] - 1]; + + /* Check for twice the same entity */ + if (found & (1 << in)) + return; + + mult[in] = dmi_data[i + 1] | (dmi_data[i + 2] << 8); + offset[in] = dmi_data[i + 3] | (dmi_data[i + 4] << 8); + + found |= 1 << in; + } + + /* entity 7: reference voltage */ + if (dmi_data[i] == 7) { + /* Check for twice the same entity */ + if (found & 0x08) + return; + + vref = dmi_data[i + 1] | (dmi_data[i + 2] << 8); + + found |= 0x08; + } + } + + if (found == 0x0F) { + for (i = 0; i < 3; i++) { + dmi_mult[i] = mult[i] * 10; + dmi_offset[i] = offset[i] * 10; + } + dmi_vref = vref; + } +} + static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) { struct i2c_client *client; @@ -586,6 +661,17 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) data->temp_max[2] = 50 + 128; } + /* Read the special DMI table for fscher and newer chips */ + if (kind == fscher || kind >= fschrc) { + dmi_walk(fschmd_dmi_decode); + if (dmi_vref == -1) { + printk(KERN_WARNING FSCHMD_NAME + ": Couldn't get voltage scaling factors from " + "BIOS DMI table, using builtin defaults\n"); + dmi_vref = 33; + } + } + /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ data->kind = kind - 1; strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE); From fe03f28cf35bf8dd0d3cba5e0c00a22530b73bfb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 19 Dec 2007 14:11:25 -0800 Subject: [PATCH 26/59] hwmon: (adt7470) Support per-sensor alarm files Remove the old alarms hack and replace it with per-sensor alarm files. Signed-off-by: Darrick J. Wong Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adt7470.c | 96 +++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index a2155605e318..747693ab2ff1 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -48,7 +48,22 @@ I2C_CLIENT_INSMOD_1(adt7470); #define ADT7470_REG_CFG 0x40 #define ADT7470_FSPD_MASK 0x04 #define ADT7470_REG_ALARM1 0x41 +#define ADT7470_R1T_ALARM 0x01 +#define ADT7470_R2T_ALARM 0x02 +#define ADT7470_R3T_ALARM 0x04 +#define ADT7470_R4T_ALARM 0x08 +#define ADT7470_R5T_ALARM 0x10 +#define ADT7470_R6T_ALARM 0x20 +#define ADT7470_R7T_ALARM 0x40 +#define ADT7470_OOL_ALARM 0x80 #define ADT7470_REG_ALARM2 0x42 +#define ADT7470_R8T_ALARM 0x01 +#define ADT7470_R9T_ALARM 0x02 +#define ADT7470_R10T_ALARM 0x04 +#define ADT7470_FAN1_ALARM 0x10 +#define ADT7470_FAN2_ALARM 0x20 +#define ADT7470_FAN3_ALARM 0x40 +#define ADT7470_FAN4_ALARM 0x80 #define ADT7470_REG_TEMP_LIMITS_BASE_ADDR 0x44 #define ADT7470_REG_TEMP_LIMITS_MAX_ADDR 0x57 #define ADT7470_REG_FAN_MIN_BASE_ADDR 0x58 @@ -97,6 +112,8 @@ I2C_CLIENT_INSMOD_1(adt7470); #define ADT7470_REG_PWM_AUTO_TEMP(x) (ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR + \ ((x) / 2)) +#define ALARM2(x) ((x) << 8) + #define ADT7470_VENDOR 0x41 #define ADT7470_DEVICE 0x70 /* datasheet only mentions a revision 2 */ @@ -136,7 +153,8 @@ struct adt7470_data { u16 fan[ADT7470_FAN_COUNT]; u16 fan_min[ADT7470_FAN_COUNT]; u16 fan_max[ADT7470_FAN_COUNT]; - u16 alarms, alarms_mask; + u16 alarm; + u16 alarms_mask; u8 force_pwm_max; u8 pwm[ADT7470_PWM_COUNT]; u8 pwm_max[ADT7470_PWM_COUNT]; @@ -260,7 +278,10 @@ static struct adt7470_data *adt7470_update_device(struct device *dev) else data->force_pwm_max = 0; - data->alarms = adt7470_read_word_data(client, ADT7470_REG_ALARM1); + data->alarm = i2c_smbus_read_byte_data(client, ADT7470_REG_ALARM1); + if (data->alarm & ADT7470_OOL_ALARM) + data->alarm |= ALARM2(i2c_smbus_read_byte_data(client, + ADT7470_REG_ALARM2)); data->alarms_mask = adt7470_read_word_data(client, ADT7470_REG_ALARM1_MASK); @@ -368,17 +389,13 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]); } -static ssize_t show_alarms(struct device *dev, +static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adt7470_data *data = adt7470_update_device(dev); - if (attr->index) - return sprintf(buf, "%x\n", data->alarms); - else - return sprintf(buf, "%x\n", data->alarms_mask); + return sprintf(buf, "%x\n", data->alarms_mask); } static ssize_t show_fan_max(struct device *dev, @@ -713,8 +730,20 @@ static ssize_t set_pwm_auto_temp(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL, 0); -static SENSOR_DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarms, NULL, 1); +static ssize_t show_alarm(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + + if (data->alarm & attr->index) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarm_mask, NULL); static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max, 0); @@ -769,6 +798,27 @@ static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7); static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8); static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_temp, NULL, 9); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, + ADT7470_R1T_ALARM); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, + ADT7470_R2T_ALARM); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, + ADT7470_R3T_ALARM); +static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, + ADT7470_R4T_ALARM); +static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL, + ADT7470_R5T_ALARM); +static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL, + ADT7470_R6T_ALARM); +static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO, show_alarm, NULL, + ADT7470_R7T_ALARM); +static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO, show_alarm, NULL, + ALARM2(ADT7470_R8T_ALARM)); +static SENSOR_DEVICE_ATTR(temp9_alarm, S_IRUGO, show_alarm, NULL, + ALARM2(ADT7470_R9T_ALARM)); +static SENSOR_DEVICE_ATTR(temp10_alarm, S_IRUGO, show_alarm, NULL, + ALARM2(ADT7470_R10T_ALARM)); + static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max, set_fan_max, 0); static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max, @@ -792,6 +842,15 @@ static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, + ALARM2(ADT7470_FAN1_ALARM)); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, + ALARM2(ADT7470_FAN2_ALARM)); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, + ALARM2(ADT7470_FAN3_ALARM)); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, + ALARM2(ADT7470_FAN4_ALARM)); + static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, show_force_pwm_max, set_force_pwm_max, 0); @@ -856,8 +915,7 @@ static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, static struct attribute *adt7470_attr[] = { - &sensor_dev_attr_alarms.dev_attr.attr, - &sensor_dev_attr_alarm_mask.dev_attr.attr, + &dev_attr_alarm_mask.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, @@ -888,6 +946,16 @@ static struct attribute *adt7470_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_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_alarm.dev_attr.attr, + &sensor_dev_attr_temp5_alarm.dev_attr.attr, + &sensor_dev_attr_temp6_alarm.dev_attr.attr, + &sensor_dev_attr_temp7_alarm.dev_attr.attr, + &sensor_dev_attr_temp8_alarm.dev_attr.attr, + &sensor_dev_attr_temp9_alarm.dev_attr.attr, + &sensor_dev_attr_temp10_alarm.dev_attr.attr, &sensor_dev_attr_fan1_max.dev_attr.attr, &sensor_dev_attr_fan2_max.dev_attr.attr, &sensor_dev_attr_fan3_max.dev_attr.attr, @@ -900,6 +968,10 @@ static struct attribute *adt7470_attr[] = &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, &sensor_dev_attr_force_pwm_max.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, From f1d8e33263abb6a3a2265ba59344c7eb002b2389 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 25 Nov 2007 16:14:44 +0100 Subject: [PATCH 27/59] hwmon: (it87) Discard a dead e-mail address Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/it87 | 2 +- drivers/hwmon/it87.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 index 5b704a40256b..f4ce1fdbeff6 100644 --- a/Documentation/hwmon/it87 +++ b/Documentation/hwmon/it87 @@ -30,7 +30,7 @@ Supported chips: Datasheet: No longer be available Authors: - Christophe Gauthron + Christophe Gauthron Jean Delvare diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0932fd53352a..2bdb153cf989 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -17,7 +17,7 @@ IT8726F Super I/O chip w/LPC interface Sis950 A clone of the IT8705F - Copyright (C) 2001 Chris Gauthron + Copyright (C) 2001 Chris Gauthron Copyright (C) 2005-2006 Jean Delvare This program is free software; you can redistribute it and/or modify @@ -1492,7 +1492,7 @@ static void __exit sm_it87_exit(void) } -MODULE_AUTHOR("Chris Gauthron , " +MODULE_AUTHOR("Chris Gauthron, " "Jean Delvare "); MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8726F, SiS950 driver"); module_param(update_vbat, bool, 0); From 0124dd78e28eec6c030f8d02929e81f05e1ce4e6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 25 Nov 2007 16:16:41 +0100 Subject: [PATCH 28/59] hwmon: (it87) Add individual alarm files The new libsensors needs this. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/it87.c | 75 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 2bdb153cf989..ca0a723cbce5 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -18,7 +18,7 @@ Sis950 A clone of the IT8705F Copyright (C) 2001 Chris Gauthron - Copyright (C) 2005-2006 Jean Delvare + Copyright (C) 2005-2007 Jean Delvare 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 @@ -780,6 +780,30 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); + static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { @@ -841,6 +865,14 @@ static struct attribute *it87_attributes[] = { &sensor_dev_attr_in5_max.dev_attr.attr, &sensor_dev_attr_in6_max.dev_attr.attr, &sensor_dev_attr_in7_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, @@ -854,6 +886,9 @@ static struct attribute *it87_attributes[] = { &sensor_dev_attr_temp1_type.dev_attr.attr, &sensor_dev_attr_temp2_type.dev_attr.attr, &sensor_dev_attr_temp3_type.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_name.attr, @@ -886,6 +921,12 @@ static struct attribute *it87_attributes_opt[] = { &sensor_dev_attr_fan3_min.dev_attr.attr, &sensor_dev_attr_fan3_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, + &sensor_dev_attr_fan5_alarm.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm2_enable.dev_attr.attr, &sensor_dev_attr_pwm3_enable.dev_attr.attr, @@ -1031,35 +1072,45 @@ static int __devinit it87_probe(struct platform_device *pdev) if ((err = device_create_file(dev, &sensor_dev_attr_fan1_input16.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan1_min16.dev_attr))) + &sensor_dev_attr_fan1_min16.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan1_alarm.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 1)) { if ((err = device_create_file(dev, &sensor_dev_attr_fan2_input16.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan2_min16.dev_attr))) + &sensor_dev_attr_fan2_min16.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan2_alarm.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 2)) { if ((err = device_create_file(dev, &sensor_dev_attr_fan3_input16.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan3_min16.dev_attr))) + &sensor_dev_attr_fan3_min16.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan3_alarm.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 3)) { if ((err = device_create_file(dev, &sensor_dev_attr_fan4_input16.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan4_min16.dev_attr))) + &sensor_dev_attr_fan4_min16.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan4_alarm.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 4)) { if ((err = device_create_file(dev, &sensor_dev_attr_fan5_input16.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan5_min16.dev_attr))) + &sensor_dev_attr_fan5_min16.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan5_alarm.dev_attr))) goto ERROR4; } } else { @@ -1070,7 +1121,9 @@ static int __devinit it87_probe(struct platform_device *pdev) || (err = device_create_file(dev, &sensor_dev_attr_fan1_min.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan1_div.dev_attr))) + &sensor_dev_attr_fan1_div.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan1_alarm.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 1)) { @@ -1079,7 +1132,9 @@ static int __devinit it87_probe(struct platform_device *pdev) || (err = device_create_file(dev, &sensor_dev_attr_fan2_min.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan2_div.dev_attr))) + &sensor_dev_attr_fan2_div.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan2_alarm.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 2)) { @@ -1088,7 +1143,9 @@ static int __devinit it87_probe(struct platform_device *pdev) || (err = device_create_file(dev, &sensor_dev_attr_fan3_min.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_fan3_div.dev_attr))) + &sensor_dev_attr_fan3_div.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan3_alarm.dev_attr))) goto ERROR4; } } From a9273cb8eea503f6b8e28bd5f613962ecba278c5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 29 Nov 2007 23:45:22 +0100 Subject: [PATCH 29/59] hwmon: (adm1026) Add individual alarm files The new libsensors needs these. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1026.c | 65 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 3e63c1486770..69b7bc411c1f 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -1244,6 +1244,43 @@ static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adm1026_data *data = adm1026_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1); +} + +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19); +static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20); +static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21); +static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22); +static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24); +static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25); +static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26); + static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); @@ -1444,87 +1481,115 @@ static struct attribute *adm1026_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in5_max.dev_attr.attr, &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in6_max.dev_attr.attr, &sensor_dev_attr_in6_min.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, &sensor_dev_attr_in7_max.dev_attr.attr, &sensor_dev_attr_in7_min.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, &sensor_dev_attr_in8_input.dev_attr.attr, &sensor_dev_attr_in8_max.dev_attr.attr, &sensor_dev_attr_in8_min.dev_attr.attr, + &sensor_dev_attr_in8_alarm.dev_attr.attr, &sensor_dev_attr_in9_input.dev_attr.attr, &sensor_dev_attr_in9_max.dev_attr.attr, &sensor_dev_attr_in9_min.dev_attr.attr, + &sensor_dev_attr_in9_alarm.dev_attr.attr, &sensor_dev_attr_in10_input.dev_attr.attr, &sensor_dev_attr_in10_max.dev_attr.attr, &sensor_dev_attr_in10_min.dev_attr.attr, + &sensor_dev_attr_in10_alarm.dev_attr.attr, &sensor_dev_attr_in11_input.dev_attr.attr, &sensor_dev_attr_in11_max.dev_attr.attr, &sensor_dev_attr_in11_min.dev_attr.attr, + &sensor_dev_attr_in11_alarm.dev_attr.attr, &sensor_dev_attr_in12_input.dev_attr.attr, &sensor_dev_attr_in12_max.dev_attr.attr, &sensor_dev_attr_in12_min.dev_attr.attr, + &sensor_dev_attr_in12_alarm.dev_attr.attr, &sensor_dev_attr_in13_input.dev_attr.attr, &sensor_dev_attr_in13_max.dev_attr.attr, &sensor_dev_attr_in13_min.dev_attr.attr, + &sensor_dev_attr_in13_alarm.dev_attr.attr, &sensor_dev_attr_in14_input.dev_attr.attr, &sensor_dev_attr_in14_max.dev_attr.attr, &sensor_dev_attr_in14_min.dev_attr.attr, + &sensor_dev_attr_in14_alarm.dev_attr.attr, &sensor_dev_attr_in15_input.dev_attr.attr, &sensor_dev_attr_in15_max.dev_attr.attr, &sensor_dev_attr_in15_min.dev_attr.attr, + &sensor_dev_attr_in15_alarm.dev_attr.attr, &sensor_dev_attr_in16_input.dev_attr.attr, &sensor_dev_attr_in16_max.dev_attr.attr, &sensor_dev_attr_in16_min.dev_attr.attr, + &sensor_dev_attr_in16_alarm.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan3_div.dev_attr.attr, &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan4_div.dev_attr.attr, &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan5_div.dev_attr.attr, &sensor_dev_attr_fan5_min.dev_attr.attr, + &sensor_dev_attr_fan5_alarm.dev_attr.attr, &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan6_div.dev_attr.attr, &sensor_dev_attr_fan6_min.dev_attr.attr, + &sensor_dev_attr_fan6_alarm.dev_attr.attr, &sensor_dev_attr_fan7_input.dev_attr.attr, &sensor_dev_attr_fan7_div.dev_attr.attr, &sensor_dev_attr_fan7_min.dev_attr.attr, + &sensor_dev_attr_fan7_alarm.dev_attr.attr, &sensor_dev_attr_fan8_input.dev_attr.attr, &sensor_dev_attr_fan8_div.dev_attr.attr, &sensor_dev_attr_fan8_min.dev_attr.attr, + &sensor_dev_attr_fan8_alarm.dev_attr.attr, &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_alarm.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, &sensor_dev_attr_temp1_offset.dev_attr.attr, &sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp3_offset.dev_attr.attr, From cb01a2312f56c93d2740e827718966b92b7cbb91 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 29 Nov 2007 23:46:42 +0100 Subject: [PATCH 30/59] hwmon: (adm1026) Whitespace cleanups Whitespace cleanups only: * Trim trailing whitespace. * Use tabs for indentation and alignment. * Add missing space after commas. * Remove extra spaces. No functional change, binary is identical before and after this patch. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1026.c | 451 ++++++++++++++++++++-------------------- 1 file changed, 227 insertions(+), 224 deletions(-) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 69b7bc411c1f..9f44ed7ebb7b 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -40,8 +40,8 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD_1(adm1026); -static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; +static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -49,46 +49,49 @@ static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, static int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -module_param_array(gpio_input,int,NULL,0); -MODULE_PARM_DESC(gpio_input,"List of GPIO pins (0-16) to program as inputs"); -module_param_array(gpio_output,int,NULL,0); -MODULE_PARM_DESC(gpio_output,"List of GPIO pins (0-16) to program as " +module_param_array(gpio_input, int, NULL, 0); +MODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs"); +module_param_array(gpio_output, int, NULL, 0); +MODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as " "outputs"); -module_param_array(gpio_inverted,int,NULL,0); -MODULE_PARM_DESC(gpio_inverted,"List of GPIO pins (0-16) to program as " +module_param_array(gpio_inverted, int, NULL, 0); +MODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as " "inverted"); -module_param_array(gpio_normal,int,NULL,0); -MODULE_PARM_DESC(gpio_normal,"List of GPIO pins (0-16) to program as " +module_param_array(gpio_normal, int, NULL, 0); +MODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as " "normal/non-inverted"); -module_param_array(gpio_fan,int,NULL,0); -MODULE_PARM_DESC(gpio_fan,"List of GPIO pins (0-7) to program as fan tachs"); +module_param_array(gpio_fan, int, NULL, 0); +MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs"); /* Many ADM1026 constants specified below */ /* The ADM1026 registers */ -#define ADM1026_REG_CONFIG1 0x00 -#define CFG1_MONITOR 0x01 -#define CFG1_INT_ENABLE 0x02 -#define CFG1_INT_CLEAR 0x04 -#define CFG1_AIN8_9 0x08 -#define CFG1_THERM_HOT 0x10 -#define CFG1_DAC_AFC 0x20 -#define CFG1_PWM_AFC 0x40 -#define CFG1_RESET 0x80 -#define ADM1026_REG_CONFIG2 0x01 +#define ADM1026_REG_CONFIG1 0x00 +#define CFG1_MONITOR 0x01 +#define CFG1_INT_ENABLE 0x02 +#define CFG1_INT_CLEAR 0x04 +#define CFG1_AIN8_9 0x08 +#define CFG1_THERM_HOT 0x10 +#define CFG1_DAC_AFC 0x20 +#define CFG1_PWM_AFC 0x40 +#define CFG1_RESET 0x80 + +#define ADM1026_REG_CONFIG2 0x01 /* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */ -#define ADM1026_REG_CONFIG3 0x07 -#define CFG3_GPIO16_ENABLE 0x01 -#define CFG3_CI_CLEAR 0x02 -#define CFG3_VREF_250 0x04 -#define CFG3_GPIO16_DIR 0x40 -#define CFG3_GPIO16_POL 0x80 -#define ADM1026_REG_E2CONFIG 0x13 -#define E2CFG_READ 0x01 -#define E2CFG_WRITE 0x02 -#define E2CFG_ERASE 0x04 -#define E2CFG_ROM 0x08 -#define E2CFG_CLK_EXT 0x80 + +#define ADM1026_REG_CONFIG3 0x07 +#define CFG3_GPIO16_ENABLE 0x01 +#define CFG3_CI_CLEAR 0x02 +#define CFG3_VREF_250 0x04 +#define CFG3_GPIO16_DIR 0x40 +#define CFG3_GPIO16_POL 0x80 + +#define ADM1026_REG_E2CONFIG 0x13 +#define E2CFG_READ 0x01 +#define E2CFG_WRITE 0x02 +#define E2CFG_ERASE 0x04 +#define E2CFG_ROM 0x08 +#define E2CFG_CLK_EXT 0x80 /* There are 10 general analog inputs and 7 dedicated inputs * They are: @@ -129,48 +132,48 @@ static u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 }; static u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f }; static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f }; -#define ADM1026_REG_FAN(nr) (0x38 + (nr)) -#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr)) -#define ADM1026_REG_FAN_DIV_0_3 0x02 -#define ADM1026_REG_FAN_DIV_4_7 0x03 +#define ADM1026_REG_FAN(nr) (0x38 + (nr)) +#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr)) +#define ADM1026_REG_FAN_DIV_0_3 0x02 +#define ADM1026_REG_FAN_DIV_4_7 0x03 -#define ADM1026_REG_DAC 0x04 -#define ADM1026_REG_PWM 0x05 +#define ADM1026_REG_DAC 0x04 +#define ADM1026_REG_PWM 0x05 -#define ADM1026_REG_GPIO_CFG_0_3 0x08 -#define ADM1026_REG_GPIO_CFG_4_7 0x09 -#define ADM1026_REG_GPIO_CFG_8_11 0x0a -#define ADM1026_REG_GPIO_CFG_12_15 0x0b +#define ADM1026_REG_GPIO_CFG_0_3 0x08 +#define ADM1026_REG_GPIO_CFG_4_7 0x09 +#define ADM1026_REG_GPIO_CFG_8_11 0x0a +#define ADM1026_REG_GPIO_CFG_12_15 0x0b /* CFG_16 in REG_CFG3 */ -#define ADM1026_REG_GPIO_STATUS_0_7 0x24 -#define ADM1026_REG_GPIO_STATUS_8_15 0x25 +#define ADM1026_REG_GPIO_STATUS_0_7 0x24 +#define ADM1026_REG_GPIO_STATUS_8_15 0x25 /* STATUS_16 in REG_STATUS4 */ -#define ADM1026_REG_GPIO_MASK_0_7 0x1c -#define ADM1026_REG_GPIO_MASK_8_15 0x1d +#define ADM1026_REG_GPIO_MASK_0_7 0x1c +#define ADM1026_REG_GPIO_MASK_8_15 0x1d /* MASK_16 in REG_MASK4 */ -#define ADM1026_REG_COMPANY 0x16 -#define ADM1026_REG_VERSTEP 0x17 +#define ADM1026_REG_COMPANY 0x16 +#define ADM1026_REG_VERSTEP 0x17 /* These are the recognized values for the above regs */ -#define ADM1026_COMPANY_ANALOG_DEV 0x41 -#define ADM1026_VERSTEP_GENERIC 0x40 -#define ADM1026_VERSTEP_ADM1026 0x44 +#define ADM1026_COMPANY_ANALOG_DEV 0x41 +#define ADM1026_VERSTEP_GENERIC 0x40 +#define ADM1026_VERSTEP_ADM1026 0x44 -#define ADM1026_REG_MASK1 0x18 -#define ADM1026_REG_MASK2 0x19 -#define ADM1026_REG_MASK3 0x1a -#define ADM1026_REG_MASK4 0x1b +#define ADM1026_REG_MASK1 0x18 +#define ADM1026_REG_MASK2 0x19 +#define ADM1026_REG_MASK3 0x1a +#define ADM1026_REG_MASK4 0x1b -#define ADM1026_REG_STATUS1 0x20 -#define ADM1026_REG_STATUS2 0x21 -#define ADM1026_REG_STATUS3 0x22 -#define ADM1026_REG_STATUS4 0x23 +#define ADM1026_REG_STATUS1 0x20 +#define ADM1026_REG_STATUS2 0x21 +#define ADM1026_REG_STATUS3 0x22 +#define ADM1026_REG_STATUS4 0x23 #define ADM1026_FAN_ACTIVATION_TEMP_HYST -6 -#define ADM1026_FAN_CONTROL_TEMP_RANGE 20 -#define ADM1026_PWM_MAX 255 +#define ADM1026_FAN_CONTROL_TEMP_RANGE 20 +#define ADM1026_PWM_MAX 255 -/* Conversions. Rounding and limit checking is only done on the TO_REG +/* Conversions. Rounding and limit checking is only done on the TO_REG * variants. Note that you should be a bit careful with which arguments * these macros are called: arguments may be evaluated more than once. */ @@ -186,47 +189,47 @@ static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f }; * The values in this table are based on Table II, page 15 of the * datasheet. */ -static int adm1026_scaling[] = { /* .001 Volts */ - 2250, 2250, 2250, 2250, 2250, 2250, - 1875, 1875, 1875, 1875, 3000, 3330, +static int adm1026_scaling[] = { /* .001 Volts */ + 2250, 2250, 2250, 2250, 2250, 2250, + 1875, 1875, 1875, 1875, 3000, 3330, 3330, 4995, 2250, 12000, 13875 }; #define NEG12_OFFSET 16000 -#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from)) -#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,adm1026_scaling[n],192),\ - 0,255)) -#define INS_FROM_REG(n,val) (SCALE(val,192,adm1026_scaling[n])) +#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from)) +#define INS_TO_REG(n, val) (SENSORS_LIMIT(SCALE(val, adm1026_scaling[n], 192),\ + 0, 255)) +#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n])) /* FAN speed is measured using 22.5kHz clock and counts for 2 pulses * and we assume a 2 pulse-per-rev fan tach signal * 22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000 */ -#define FAN_TO_REG(val,div) ((val)<=0 ? 0xff : SENSORS_LIMIT(1350000/((val)*\ - (div)),1,254)) -#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==0xff ? 0 : 1350000/((val)*\ - (div))) +#define FAN_TO_REG(val, div) ((val) <= 0 ? 0xff : \ + SENSORS_LIMIT(1350000/((val)*(div)), 1, 254)) +#define FAN_FROM_REG(val, div) ((val) == 0 ? -1:(val) == 0xff ? 0 : \ + 1350000/((val)*(div))) #define DIV_FROM_REG(val) (1<<(val)) -#define DIV_TO_REG(val) ((val)>=8 ? 3 : (val)>=4 ? 2 : (val)>=2 ? 1 : 0) +#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0) /* Temperature is reported in 1 degC increments */ #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ - -127,127)) + -127, 127)) #define TEMP_FROM_REG(val) ((val) * 1000) #define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ - -127,127)) + -127, 127)) #define OFFSET_FROM_REG(val) ((val) * 1000) -#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255)) +#define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255)) #define PWM_FROM_REG(val) (val) #define PWM_MIN_TO_REG(val) ((val) & 0xf0) #define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4)) -/* Analog output is a voltage, and scaled to millivolts. The datasheet - * indicates that the DAC could be used to drive the fans, but in our +/* Analog output is a voltage, and scaled to millivolts. The datasheet + * indicates that the DAC could be used to drive the fans, but in our * example board (Arima HDAMA) it isn't connected to the fans at all. */ -#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500),0,255)) +#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500), 0, 255)) #define DAC_FROM_REG(val) (((val)*2500)/255) /* Typically used with systems using a v9.1 VRM spec ? */ @@ -243,8 +246,8 @@ static int adm1026_scaling[] = { /* .001 Volts */ * So, we keep the config data up to date in the cache * when it is written and only sample it once every 5 *minutes* */ -#define ADM1026_DATA_INTERVAL (1 * HZ) -#define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ) +#define ADM1026_DATA_INTERVAL (1 * HZ) +#define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ) /* We allow for multiple chips in a single system. * @@ -268,30 +271,30 @@ struct adm1026_data { unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ - u8 in[17]; /* Register value */ - u8 in_max[17]; /* Register value */ - u8 in_min[17]; /* Register value */ - s8 temp[3]; /* Register value */ - s8 temp_min[3]; /* Register value */ - s8 temp_max[3]; /* Register value */ - s8 temp_tmin[3]; /* Register value */ - s8 temp_crit[3]; /* Register value */ - s8 temp_offset[3]; /* Register value */ - u8 fan[8]; /* Register value */ - u8 fan_min[8]; /* Register value */ - u8 fan_div[8]; /* Decoded value */ - struct pwm_data pwm1; /* Pwm control values */ - int vid; /* Decoded value */ - u8 vrm; /* VRM version */ + u8 in[17]; /* Register value */ + u8 in_max[17]; /* Register value */ + u8 in_min[17]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_min[3]; /* Register value */ + s8 temp_max[3]; /* Register value */ + s8 temp_tmin[3]; /* Register value */ + s8 temp_crit[3]; /* Register value */ + s8 temp_offset[3]; /* Register value */ + u8 fan[8]; /* Register value */ + u8 fan_min[8]; /* Register value */ + u8 fan_div[8]; /* Decoded value */ + struct pwm_data pwm1; /* Pwm control values */ + int vid; /* Decoded value */ + u8 vrm; /* VRM version */ u8 analog_out; /* Register value (DAC) */ - long alarms; /* Register encoding, combined */ - long alarm_mask; /* Register encoding, combined */ - long gpio; /* Register encoding, combined */ - long gpio_mask; /* Register encoding, combined */ - u8 gpio_config[17]; /* Decoded value */ - u8 config1; /* Register value */ - u8 config2; /* Register value */ - u8 config3; /* Register value */ + long alarms; /* Register encoding, combined */ + long alarm_mask; /* Register encoding, combined */ + long gpio; /* Register encoding, combined */ + long gpio_mask; /* Register encoding, combined */ + u8 gpio_config[17]; /* Decoded value */ + u8 config1; /* Register value */ + u8 config2; /* Register value */ + u8 config3; /* Register value */ }; static int adm1026_attach_adapter(struct i2c_adapter *adapter); @@ -301,7 +304,7 @@ static int adm1026_detach_client(struct i2c_client *client); static int adm1026_read_value(struct i2c_client *client, u8 reg); static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); static void adm1026_print_gpio(struct i2c_client *client); -static void adm1026_fixup_gpio(struct i2c_client *client); +static void adm1026_fixup_gpio(struct i2c_client *client); static struct adm1026_data *adm1026_update_device(struct device *dev); static void adm1026_init_client(struct i2c_client *client); @@ -311,7 +314,7 @@ static struct i2c_driver adm1026_driver = { .name = "adm1026", }, .attach_adapter = adm1026_attach_adapter, - .detach_client = adm1026_detach_client, + .detach_client = adm1026_detach_client, }; static int adm1026_attach_adapter(struct i2c_adapter *adapter) @@ -355,7 +358,7 @@ static void adm1026_init_client(struct i2c_client *client) int value, i; struct adm1026_data *data = i2c_get_clientdata(client); - dev_dbg(&client->dev, "Initializing device\n"); + dev_dbg(&client->dev, "Initializing device\n"); /* Read chip config */ data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); @@ -426,10 +429,10 @@ static void adm1026_init_client(struct i2c_client *client) * configured, we don't want to mess with them. * If they weren't, the default is 100% PWM, no * control and will suffice until 'sensors -s' - * can be run by the user. We DO set the default + * can be run by the user. We DO set the default * value for pwm1.auto_pwm_min to its maximum * so that enabling automatic pwm fan control - * without first setting a value for pwm1.auto_pwm_min + * without first setting a value for pwm1.auto_pwm_min * will not result in potentially dangerous fan speed decrease. */ data->pwm1.auto_pwm_min=255; @@ -453,7 +456,7 @@ static void adm1026_init_client(struct i2c_client *client) static void adm1026_print_gpio(struct i2c_client *client) { struct adm1026_data *data = i2c_get_clientdata(client); - int i; + int i; dev_dbg(&client->dev, "GPIO config is:"); for (i = 0;i <= 7;++i) { @@ -477,7 +480,7 @@ static void adm1026_print_gpio(struct i2c_client *client) data->gpio_config[16] & 0x02 ? "" : "!", data->gpio_config[16] & 0x01 ? "OUT" : "IN"); } else { - /* GPIO16 is THERM */ + /* GPIO16 is THERM */ dev_dbg(&client->dev, "\tTHERM\n"); } } @@ -485,8 +488,8 @@ static void adm1026_print_gpio(struct i2c_client *client) static void adm1026_fixup_gpio(struct i2c_client *client) { struct adm1026_data *data = i2c_get_clientdata(client); - int i; - int value; + int i; + int value; /* Make the changes requested. */ /* We may need to unlock/stop monitoring or soft-reset the @@ -516,14 +519,14 @@ static void adm1026_fixup_gpio(struct i2c_client *client) } } - /* Inverted */ + /* Inverted */ for (i = 0;i <= 16;++i) { if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) { data->gpio_config[gpio_inverted[i]] &= ~ 0x02; } } - /* Normal overrides inverted */ + /* Normal overrides inverted */ for (i = 0;i <= 16;++i) { if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) { data->gpio_config[gpio_normal[i]] |= 0x02; @@ -569,7 +572,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) if (!data->valid || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { /* Things that change quickly */ - dev_dbg(&client->dev,"Reading sensor values\n"); + dev_dbg(&client->dev, "Reading sensor values\n"); for (i = 0;i <= 16;++i) { data->in[i] = adm1026_read_value(client, ADM1026_REG_IN[i]); @@ -582,18 +585,18 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) for (i = 0;i <= 2;++i) { /* NOTE: temp[] is s8 and we assume 2's complement - * "conversion" in the assignment */ + * "conversion" in the assignment */ data->temp[i] = adm1026_read_value(client, ADM1026_REG_TEMP[i]); } - data->pwm1.pwm = adm1026_read_value(client, + data->pwm1.pwm = adm1026_read_value(client, ADM1026_REG_PWM); - data->analog_out = adm1026_read_value(client, + data->analog_out = adm1026_read_value(client, ADM1026_REG_DAC); /* GPIO16 is MSbit of alarms, move it to gpio */ alarms = adm1026_read_value(client, ADM1026_REG_STATUS4); - gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ + gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ alarms &= 0x7f; alarms <<= 8; alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3); @@ -604,24 +607,24 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) data->alarms = alarms; /* Read the GPIO values */ - gpio |= adm1026_read_value(client, + gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_8_15); gpio <<= 8; - gpio |= adm1026_read_value(client, + gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_0_7); data->gpio = gpio; data->last_reading = jiffies; - }; /* last_reading */ + }; /* last_reading */ if (!data->valid || time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) { /* Things that don't change often */ dev_dbg(&client->dev, "Reading config values\n"); for (i = 0;i <= 16;++i) { - data->in_min[i] = adm1026_read_value(client, + data->in_min[i] = adm1026_read_value(client, ADM1026_REG_IN_MIN[i]); - data->in_max[i] = adm1026_read_value(client, + data->in_max[i] = adm1026_read_value(client, ADM1026_REG_IN_MAX[i]); } @@ -629,32 +632,32 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); for (i = 0;i <= 7;++i) { - data->fan_min[i] = adm1026_read_value(client, + data->fan_min[i] = adm1026_read_value(client, ADM1026_REG_FAN_MIN(i)); data->fan_div[i] = DIV_FROM_REG(value & 0x03); value >>= 2; } for (i = 0; i <= 2; ++i) { - /* NOTE: temp_xxx[] are s8 and we assume 2's + /* NOTE: temp_xxx[] are s8 and we assume 2's * complement "conversion" in the assignment */ - data->temp_min[i] = adm1026_read_value(client, + data->temp_min[i] = adm1026_read_value(client, ADM1026_REG_TEMP_MIN[i]); - data->temp_max[i] = adm1026_read_value(client, + data->temp_max[i] = adm1026_read_value(client, ADM1026_REG_TEMP_MAX[i]); - data->temp_tmin[i] = adm1026_read_value(client, + data->temp_tmin[i] = adm1026_read_value(client, ADM1026_REG_TEMP_TMIN[i]); - data->temp_crit[i] = adm1026_read_value(client, + data->temp_crit[i] = adm1026_read_value(client, ADM1026_REG_TEMP_THERM[i]); - data->temp_offset[i] = adm1026_read_value(client, + data->temp_offset[i] = adm1026_read_value(client, ADM1026_REG_TEMP_OFFSET[i]); } /* Read the STATUS/alarm masks */ - alarms = adm1026_read_value(client, ADM1026_REG_MASK4); - gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ - alarms = (alarms & 0x7f) << 8; + alarms = adm1026_read_value(client, ADM1026_REG_MASK4); + gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ + alarms = (alarms & 0x7f) << 8; alarms |= adm1026_read_value(client, ADM1026_REG_MASK3); alarms <<= 8; alarms |= adm1026_read_value(client, ADM1026_REG_MASK2); @@ -663,24 +666,24 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) data->alarm_mask = alarms; /* Read the GPIO values */ - gpio |= adm1026_read_value(client, + gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_8_15); gpio <<= 8; gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7); data->gpio_mask = gpio; /* Read various values from CONFIG1 */ - data->config1 = adm1026_read_value(client, + data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); if (data->config1 & CFG1_PWM_AFC) { data->pwm1.enable = 2; - data->pwm1.auto_pwm_min = + data->pwm1.auto_pwm_min = PWM_MIN_FROM_REG(data->pwm1.pwm); } /* Read the GPIO config */ - data->config2 = adm1026_read_value(client, + data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); - data->config3 = adm1026_read_value(client, + data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); data->gpio_config[16] = (data->config3 >> 6) & 0x03; @@ -695,7 +698,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) } data->last_config = jiffies; - }; /* last_config */ + }; /* last_config */ dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); data->vid = (data->gpio >> 11) & 0x1f; @@ -710,15 +713,15 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr])); + return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr])); } static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, char *buf) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr])); + struct adm1026_data *data = adm1026_update_device(dev); + return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr])); } static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -733,7 +736,7 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, data->in_min[nr] = INS_TO_REG(nr, val); adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); mutex_unlock(&data->update_lock); - return count; + return count; } static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, char *buf) @@ -741,7 +744,7 @@ static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr])); + return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr])); } static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -788,13 +791,13 @@ in_reg(15); static ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in[16]) - + return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) - NEG12_OFFSET); } static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf) { - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_min[16]) + struct adm1026_data *data = adm1026_update_device(dev); + return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16]) - NEG12_OFFSET); } static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -807,12 +810,12 @@ static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, c data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); mutex_unlock(&data->update_lock); - return count; + return count; } static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_max[16]) + return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16]) - NEG12_OFFSET); } static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -843,7 +846,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], data->fan_div[nr])); } static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, @@ -852,7 +855,7 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], data->fan_div[nr])); } static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, @@ -872,10 +875,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, return count; } -#define fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ - offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ +#define fan_offset(offset) \ +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ + offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ show_fan_min, set_fan_min, offset - 1); fan_offset(1); @@ -892,8 +895,8 @@ static void fixup_fan_min(struct device *dev, int fan, int old_div) { struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); - int new_min; - int new_div = data->fan_div[fan]; + int new_min; + int new_div = data->fan_div[fan]; /* 0 and 0xff are special. Don't adjust them */ if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) { @@ -913,7 +916,7 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", data->fan_div[nr]); + return sprintf(buf, "%d\n", data->fan_div[nr]); } static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -922,10 +925,10 @@ 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, shift; val = simple_strtol(buf, NULL, 10); - new_div = DIV_TO_REG(val); + new_div = DIV_TO_REG(val); if (new_div == 0) { return -EINVAL; } @@ -946,14 +949,14 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, } if (data->fan_div[nr] != orig_div) { - fixup_fan_min(dev,nr,orig_div); + fixup_fan_min(dev, nr, orig_div); } mutex_unlock(&data->update_lock); return count; } -#define fan_offset_div(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ +#define fan_offset_div(offset) \ +static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ show_fan_div, set_fan_div, offset - 1); fan_offset_div(1); @@ -972,7 +975,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr])); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); } static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, char *buf) @@ -980,7 +983,7 @@ static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr])); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); } static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1004,7 +1007,7 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr])); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); } static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1024,7 +1027,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, } #define temp_reg(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ NULL, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ show_temp_min, set_temp_min, offset - 1); \ @@ -1042,7 +1045,7 @@ static ssize_t show_temp_offset(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr])); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); } static ssize_t set_temp_offset(struct device *dev, struct device_attribute *attr, const char *buf, @@ -1076,7 +1079,7 @@ static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG( + return sprintf(buf, "%d\n", TEMP_FROM_REG( ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr])); } static ssize_t show_temp_auto_point2_temp(struct device *dev, @@ -1085,7 +1088,7 @@ static ssize_t show_temp_auto_point2_temp(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] + ADM1026_FAN_CONTROL_TEMP_RANGE)); } static ssize_t show_temp_auto_point1_temp(struct device *dev, @@ -1094,7 +1097,7 @@ static ssize_t show_temp_auto_point1_temp(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr])); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr])); } static ssize_t set_temp_auto_point1_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1113,13 +1116,13 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev, return count; } -#define temp_auto_point(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR, \ - show_temp_auto_point1_temp, set_temp_auto_point1_temp, \ - offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO, \ - show_temp_auto_point1_temp_hyst, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \ +#define temp_auto_point(offset) \ +static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, \ + S_IRUGO | S_IWUSR, show_temp_auto_point1_temp, \ + set_temp_auto_point1_temp, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\ + show_temp_auto_point1_temp_hyst, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \ show_temp_auto_point2_temp, NULL, offset - 1); temp_auto_point(1); @@ -1130,7 +1133,7 @@ static ssize_t show_temp_crit_enable(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", (data->config1 & CFG1_THERM_HOT) >> 4); + return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4); } static ssize_t set_temp_crit_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1142,7 +1145,7 @@ static ssize_t set_temp_crit_enable(struct device *dev, if ((val == 1) || (val==0)) { mutex_lock(&data->update_lock); data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); - adm1026_write_value(client, ADM1026_REG_CONFIG1, + adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1); mutex_unlock(&data->update_lock); } @@ -1163,7 +1166,7 @@ static ssize_t show_temp_crit(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr])); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); } static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1193,7 +1196,7 @@ temp_crit_reg(3); static ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", DAC_FROM_REG(data->analog_out)); + return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out)); } static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1209,20 +1212,20 @@ static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *a return count; } -static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, +static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, set_analog_out_reg); static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm)); + return sprintf(buf, "%d\n", vid_from_reg(data->vid & 0x3f, data->vrm)); } static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = dev_get_drvdata(dev); - return sprintf(buf,"%d\n", data->vrm); + return sprintf(buf, "%d\n", data->vrm); } static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1284,7 +1287,7 @@ static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26); static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%ld\n", data->alarm_mask); + return sprintf(buf, "%ld\n", data->alarm_mask); } static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1320,7 +1323,7 @@ static DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask, static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%ld\n", data->gpio); + return sprintf(buf, "%ld\n", data->gpio); } static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1328,16 +1331,16 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - long gpio; + long gpio; mutex_lock(&data->update_lock); data->gpio = val & 0x1ffff; gpio = data->gpio; - adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff); + adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff); gpio >>= 8; - adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff); + adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff); gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); - adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff); + adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff); mutex_unlock(&data->update_lock); return count; } @@ -1348,7 +1351,7 @@ static DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio); static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%ld\n", data->gpio_mask); + return sprintf(buf, "%ld\n", data->gpio_mask); } static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1356,16 +1359,16 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - long mask; + long mask; mutex_lock(&data->update_lock); data->gpio_mask = val & 0x1ffff; mask = data->gpio_mask; - adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff); + adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff); mask >>= 8; - adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff); + adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff); mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); - adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff); + adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff); mutex_unlock(&data->update_lock); return count; } @@ -1375,7 +1378,7 @@ static DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask); static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm1.pwm)); + return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm)); } static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1396,7 +1399,7 @@ static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, co static ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min); + return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min); } static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1406,10 +1409,10 @@ static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *att int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); - data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); + data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255); if (data->pwm1.enable == 2) { /* apply immediately */ data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | - PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); + PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } mutex_unlock(&data->update_lock); @@ -1417,12 +1420,12 @@ static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *att } static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf,"%d\n", ADM1026_PWM_MAX); + return sprintf(buf, "%d\n", ADM1026_PWM_MAX); } static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf,"%d\n", data->pwm1.enable); + return sprintf(buf, "%d\n", data->pwm1.enable); } static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1430,7 +1433,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - int old_enable; + int old_enable; if ((val >= 0) && (val < 3)) { mutex_lock(&data->update_lock); @@ -1440,15 +1443,15 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, | ((val == 2) ? CFG1_PWM_AFC : 0); adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1); - if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */ + if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */ data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | - PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); - adm1026_write_value(client, ADM1026_REG_PWM, + PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); + adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } else if (!((old_enable == 1) && (val == 1))) { /* set pwm to safe value */ data->pwm1.pwm = 255; - adm1026_write_value(client, ADM1026_REG_PWM, + adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } mutex_unlock(&data->update_lock); @@ -1457,20 +1460,20 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, } /* enable PWM fan control */ -static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); -static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); -static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); -static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, +static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); +static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); +static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); +static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable); -static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, +static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable); -static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, +static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable); -static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm_min, set_auto_pwm_min); -static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm_min, set_auto_pwm_min); -static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm_min, set_auto_pwm_min); static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); @@ -1695,7 +1698,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, dev_dbg(&new_client->dev, ": Autodetection " "failed\n"); /* Not an ADM1026 ... */ - if (kind == 0) { /* User used force=x,y */ + if (kind == 0) { /* User used force=x,y */ dev_err(&adapter->dev, "Generic ADM1026 not " "found at %d,0x%02x. Try " "force_adm1026.\n", @@ -1775,14 +1778,14 @@ static int __init sm_adm1026_init(void) return i2c_add_driver(&adm1026_driver); } -static void __exit sm_adm1026_exit(void) +static void __exit sm_adm1026_exit(void) { i2c_del_driver(&adm1026_driver); } MODULE_LICENSE("GPL"); MODULE_AUTHOR("Philip Pokorny , " - "Justin Thiessen "); + "Justin Thiessen "); MODULE_DESCRIPTION("ADM1026 driver"); module_init(sm_adm1026_init); From f67fdabfb94b0bb96623a4b48d22be5329a06277 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 1 Dec 2007 11:24:17 +0100 Subject: [PATCH 31/59] hwmon: (adm1026) More cleanups (updated) Various cleanups: * Drop an unused define. * Drop unused struct member "type". * Drop one useless instruction. * Drop redundant initializations to 0. * Rename new_client to client. * Drop a useless cast. * Minor code cleanup. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1026.c | 52 +++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 9f44ed7ebb7b..a20af03f4fc6 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -232,9 +232,6 @@ static int adm1026_scaling[] = { /* .001 Volts */ #define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500), 0, 255)) #define DAC_FROM_REG(val) (((val)*2500)/255) -/* Typically used with systems using a v9.1 VRM spec ? */ -#define ADM1026_INIT_VRM 91 - /* Chip sampling rates * * Some sensors are not updated more frequently than once per second @@ -264,7 +261,6 @@ struct pwm_data { struct adm1026_data { struct i2c_client client; struct device *hwmon_dev; - enum chips type; struct mutex update_lock; int valid; /* !=0 if following fields are valid */ @@ -387,7 +383,6 @@ static void adm1026_init_client(struct i2c_client *client) "and temp limits enabled.\n"); } - value = data->config3; if (data->config3 & CFG3_GPIO16_ENABLE) { dev_dbg(&client->dev, "GPIO16 enabled. THERM " "pin disabled.\n"); @@ -1230,8 +1225,7 @@ static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, c static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); data->vrm = simple_strtol(buf, NULL, 10); return count; @@ -1242,7 +1236,7 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) { struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%ld\n", (long) (data->alarms)); + return sprintf(buf, "%ld\n", data->alarms); } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); @@ -1641,7 +1635,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, int kind) { int company, verstep; - struct i2c_client *new_client; + struct i2c_client *client; struct adm1026_data *data; int err = 0; const char *type_name = ""; @@ -1660,26 +1654,25 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &adm1026_driver; - new_client->flags = 0; + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1026_driver; /* Now, we do the remaining detection. */ - company = adm1026_read_value(new_client, ADM1026_REG_COMPANY); - verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP); + company = adm1026_read_value(client, ADM1026_REG_COMPANY); + verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP); - dev_dbg(&new_client->dev, "Detecting device at %d,0x%02x with" + dev_dbg(&client->dev, "Detecting device at %d,0x%02x with" " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", - i2c_adapter_id(new_client->adapter), new_client->addr, + i2c_adapter_id(client->adapter), client->addr, company, verstep); /* If auto-detecting, Determine the chip type. */ if (kind <= 0) { - dev_dbg(&new_client->dev, "Autodetecting device at %d,0x%02x " + dev_dbg(&client->dev, "Autodetecting device at %d,0x%02x " "...\n", i2c_adapter_id(adapter), address); if (company == ADM1026_COMPANY_ANALOG_DEV && verstep == ADM1026_VERSTEP_ADM1026) { @@ -1695,7 +1688,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, verstep); kind = any_chip; } else { - dev_dbg(&new_client->dev, ": Autodetection " + dev_dbg(&client->dev, ": Autodetection " "failed\n"); /* Not an ADM1026 ... */ if (kind == 0) { /* User used force=x,y */ @@ -1704,7 +1697,6 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, "force_adm1026.\n", i2c_adapter_id(adapter), address); } - err = 0; goto exitfree; } } @@ -1723,28 +1715,26 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, err = -EFAULT; goto exitfree; } - strlcpy(new_client->name, type_name, I2C_NAME_SIZE); + strlcpy(client->name, type_name, I2C_NAME_SIZE); /* Fill in the remaining client fields */ - data->type = kind; - data->valid = 0; mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto exitfree; /* Set the VRM version */ data->vrm = vid_which_vrm(); /* Initialize the ADM1026 chip */ - adm1026_init_client(new_client); + adm1026_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1026_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group))) goto exitdetach; - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exitremove; @@ -1754,9 +1744,9 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, /* Error out and cleanup code */ exitremove: - sysfs_remove_group(&new_client->dev.kobj, &adm1026_group); + sysfs_remove_group(&client->dev.kobj, &adm1026_group); exitdetach: - i2c_detach_client(new_client); + i2c_detach_client(client); exitfree: kfree(data); exit: From 5b34dbcd88251508d02e48ad9b0f9b8232a13ee0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 29 Nov 2007 23:47:54 +0100 Subject: [PATCH 32/59] hwmon: (adm1026) Don't create files for missing inputs On the ADM1026, pins 27 and 28 can be used for two different functions: either temp3, or in8+in9. We should only create the sysfs files for the function that is configured, otherwise it is confusing for the user. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1026.c | 70 +++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index a20af03f4fc6..8002f68240c4 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -1507,14 +1507,6 @@ static struct attribute *adm1026_attributes[] = { &sensor_dev_attr_in7_max.dev_attr.attr, &sensor_dev_attr_in7_min.dev_attr.attr, &sensor_dev_attr_in7_alarm.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in8_alarm.dev_attr.attr, - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in9_max.dev_attr.attr, - &sensor_dev_attr_in9_min.dev_attr.attr, - &sensor_dev_attr_in9_alarm.dev_attr.attr, &sensor_dev_attr_in10_input.dev_attr.attr, &sensor_dev_attr_in10_max.dev_attr.attr, &sensor_dev_attr_in10_min.dev_attr.attr, @@ -1583,28 +1575,18 @@ static struct attribute *adm1026_attributes[] = { &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, &sensor_dev_attr_temp1_offset.dev_attr.attr, &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, &dev_attr_temp1_crit_enable.attr, &dev_attr_temp2_crit_enable.attr, - &dev_attr_temp3_crit_enable.attr, &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, &dev_attr_alarms.attr, @@ -1619,10 +1601,8 @@ static struct attribute *adm1026_attributes[] = { &dev_attr_pwm3_enable.attr, &dev_attr_temp1_auto_point1_pwm.attr, &dev_attr_temp2_auto_point1_pwm.attr, - &dev_attr_temp3_auto_point1_pwm.attr, &dev_attr_temp1_auto_point2_pwm.attr, &dev_attr_temp2_auto_point2_pwm.attr, - &dev_attr_temp3_auto_point2_pwm.attr, &dev_attr_analog_out.attr, NULL }; @@ -1631,6 +1611,40 @@ static const struct attribute_group adm1026_group = { .attrs = adm1026_attributes, }; +static struct attribute *adm1026_attributes_temp3[] = { + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_offset.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp3_crit.dev_attr.attr, + &dev_attr_temp3_crit_enable.attr, + &dev_attr_temp3_auto_point1_pwm.attr, + &dev_attr_temp3_auto_point2_pwm.attr, +}; + +static const struct attribute_group adm1026_group_temp3 = { + .attrs = adm1026_attributes_temp3, +}; + +static struct attribute *adm1026_attributes_in8_9[] = { + &sensor_dev_attr_in8_input.dev_attr.attr, + &sensor_dev_attr_in8_max.dev_attr.attr, + &sensor_dev_attr_in8_min.dev_attr.attr, + &sensor_dev_attr_in8_alarm.dev_attr.attr, + &sensor_dev_attr_in9_input.dev_attr.attr, + &sensor_dev_attr_in9_max.dev_attr.attr, + &sensor_dev_attr_in9_min.dev_attr.attr, + &sensor_dev_attr_in9_alarm.dev_attr.attr, +}; + +static const struct attribute_group adm1026_group_in8_9 = { + .attrs = adm1026_attributes_in8_9, +}; + static int adm1026_detect(struct i2c_adapter *adapter, int address, int kind) { @@ -1733,6 +1747,14 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group))) goto exitdetach; + if (data->config1 & CFG1_AIN8_9) + err = sysfs_create_group(&client->dev.kobj, + &adm1026_group_in8_9); + else + err = sysfs_create_group(&client->dev.kobj, + &adm1026_group_temp3); + if (err) + goto exitremove; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -1745,6 +1767,10 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, /* Error out and cleanup code */ exitremove: sysfs_remove_group(&client->dev.kobj, &adm1026_group); + if (data->config1 & CFG1_AIN8_9) + sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); + else + sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); exitdetach: i2c_detach_client(client); exitfree: @@ -1758,6 +1784,10 @@ static int adm1026_detach_client(struct i2c_client *client) struct adm1026_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1026_group); + if (data->config1 & CFG1_AIN8_9) + sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); + else + sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); i2c_detach_client(client); kfree(data); return 0; From 05663368d2138c14fa1b9aa8eeca4ca9a33d7c77 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 30 Nov 2007 23:51:24 +0100 Subject: [PATCH 33/59] hwmon: (w83781d) Drop W83627HF support The W83627HF hardware monitoring features are supported by the w83627hf driver for several years now. Support by the w83781d has been advertised as deprecated 6 months ago, it's about time to see it go. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/w83781d | 18 ++++++------------ drivers/hwmon/Kconfig | 6 +++--- drivers/hwmon/w83781d.c | 29 +++++------------------------ 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/Documentation/hwmon/w83781d b/Documentation/hwmon/w83781d index dbeadb269a69..6f800a0283e9 100644 --- a/Documentation/hwmon/w83781d +++ b/Documentation/hwmon/w83781d @@ -14,10 +14,6 @@ Supported chips: Prefix: 'w83783s' Addresses scanned: I2C 0x2d Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83783s.pdf - * Winbond W83627HF - Prefix: 'w83627hf' - Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports) - Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf * Asus AS99127F Prefix: 'as99127f' Addresses scanned: I2C 0x28 - 0x2f @@ -50,20 +46,18 @@ force_subclients=bus,caddr,saddr,saddr Description ----------- -This driver implements support for the Winbond W83781D, W83782D, W83783S, -W83627HF chips, and the Asus AS99127F chips. We will refer to them -collectively as W8378* chips. +This driver implements support for the Winbond W83781D, W83782D, W83783S +chips, and the Asus AS99127F chips. We will refer to them collectively as +W8378* chips. There is quite some difference between these chips, but they are similar enough that it was sensible to put them together in one driver. -The W83627HF chip is assumed to be identical to the ISA W83782D. The Asus chips are similar to an I2C-only W83782D. Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA as99127f 7 3 0 3 0x31 0x12c3 yes no as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes -w83627hf 9 3 2 3 0x21 0x5ca3 yes yes(LPC) w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no @@ -143,9 +137,9 @@ Individual alarm and beep bits: 0x000400: in6 0x000800: fan3 0x001000: chassis -0x002000: temp3 (W83782D and W83627HF only) -0x010000: in7 (W83782D and W83627HF only) -0x020000: in8 (W83782D and W83627HF only) +0x002000: temp3 (W83782D only) +0x010000: in7 (W83782D only) +0x020000: in8 (W83782D only) If an alarm triggers, it will remain triggered until the hardware register is read at least once. This means that the cause for the alarm may diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index af43d566d770..27e0b34ead5f 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -631,13 +631,13 @@ config SENSORS_VT8231 will be called vt8231. config SENSORS_W83781D - tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F" + tristate "Winbond W83781D, W83782D, W83783S, Asus AS99127F" depends on I2C select HWMON_VID help If you say yes here you get support for the Winbond W8378x series - of sensor chips: the W83781D, W83782D, W83783S and W83627HF, - and the similar Asus AS99127F. + of sensor chips: the W83781D, W83782D and W83783S, and the similar + Asus AS99127F. This driver can also be built as a module. If so, the module will be called w83781d. diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index d38b9ede3abd..8d4d1acbf650 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -28,7 +28,6 @@ as99127f 7 3 0 3 0x31 0x12c3 yes no as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes - w83627hf 9 3 2 3 0x21 0x5ca3 yes yes(LPC) w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no @@ -59,7 +58,7 @@ static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, static unsigned short isa_address = 0x290; /* Insmod parameters */ -I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f); +I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f); I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " "{bus, clientaddr, subclientaddr1, subclientaddr2}"); @@ -113,7 +112,7 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); #define W83781D_REG_ALARM1 0x41 #define W83781D_REG_ALARM2 0x42 -/* Real-time status (W83782D, W83783S, W83627HF) */ +/* Real-time status (W83782D, W83783S) */ #define W83782D_REG_ALARM1 0x459 #define W83782D_REG_ALARM2 0x45A #define W83782D_REG_ALARM3 0x45B @@ -962,8 +961,6 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, client_name = "w83782d subclient"; else if (kind == w83783s) client_name = "w83783s subclient"; - else if (kind == w83627hf) - client_name = "w83627hf subclient"; else if (kind == as99127f) client_name = "as99127f subclient"; @@ -1267,8 +1264,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) kind = w83782d; else if (val1 == 0x40 && vendid == winbond && address == 0x2d) kind = w83783s; - else if (val1 == 0x21 && vendid == winbond) - kind = w83627hf; else if (val1 == 0x31) kind = as99127f; else { @@ -1287,8 +1282,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) client_name = "w83782d"; } else if (kind == w83783s) { client_name = "w83783s"; - } else if (kind == w83627hf) { - client_name = "w83627hf"; } else if (kind == as99127f) { client_name = "as99127f"; } @@ -1395,10 +1388,6 @@ w83781d_isa_probe(struct platform_device *pdev) reg = w83781d_read_value(data, W83781D_REG_WCHIPID); switch (reg) { - case 0x21: - data->type = w83627hf; - name = "w83627hf"; - break; case 0x30: data->type = w83782d; name = "w83782d"; @@ -1598,11 +1587,6 @@ w83781d_init_device(struct device *dev) int type = data->type; u8 tmp; - if (type == w83627hf) - dev_info(dev, "The W83627HF chip is better supported by the " - "w83627hf driver, support will be dropped from the " - "w83781d driver soon\n"); - if (reset && type != as99127f) { /* this resets registers we don't have documentation for on the as99127f */ /* Resetting the chip has been the default for a long time, @@ -1716,8 +1700,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) w83781d_read_value(data, W83781D_REG_IN_MIN(i)); data->in_max[i] = w83781d_read_value(data, W83781D_REG_IN_MAX(i)); - if ((data->type != w83782d) - && (data->type != w83627hf) && (i == 6)) + if ((data->type != w83782d) && (i == 6)) break; } for (i = 0; i < 3; i++) { @@ -1775,7 +1758,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) data->fan_div[1] |= (i >> 4) & 0x04; data->fan_div[2] |= (i >> 5) & 0x04; } - if ((data->type == w83782d) || (data->type == w83627hf)) { + if (data->type == w83782d) { data->alarms = w83781d_read_value(data, W83782D_REG_ALARM1) | (w83781d_read_value(data, @@ -1885,13 +1868,11 @@ w83781d_isa_found(unsigned short address) outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET); val = inb_p(address + W83781D_DATA_REG_OFFSET); if ((val & 0xfe) == 0x10 /* W83781D */ - || val == 0x30 /* W83782D */ - || val == 0x21) /* W83627HF */ + || val == 0x30) /* W83782D */ found = 1; if (found) pr_info("w83781d: Found a %s chip at %#x\n", - val == 0x21 ? "W83627HF" : val == 0x30 ? "W83782D" : "W83781D", (int)address); release: From 293c09971631d22f8e91402f58955ccaada9dbde Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 30 Nov 2007 23:52:44 +0100 Subject: [PATCH 34/59] hwmon: (w83781d) Misc cleanups * Drop unused defines * Drop unused driver ID * Remove trailing whitespace Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83781d.c | 13 ++++--------- include/linux/i2c-id.h | 1 - 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 8d4d1acbf650..7421f6ea53e1 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -151,10 +151,6 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; #define W83781D_DEFAULT_BETA 3435 -/* RT Table registers */ -#define W83781D_REG_RT_IDX 0x50 -#define W83781D_REG_RT_VAL 0x51 - /* Conversions */ #define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255) #define IN_FROM_REG(val) ((val) * 16) @@ -269,7 +265,6 @@ static struct i2c_driver w83781d_driver = { .driver = { .name = "w83781d", }, - .id = I2C_DRIVERID_W83781D, .attach_adapter = w83781d_attach_adapter, .detach_client = w83781d_detach_client, }; @@ -694,7 +689,7 @@ store_fan_div(struct device *dev, struct device_attribute *da, unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); - + /* Save fan_min */ min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -1000,7 +995,7 @@ ERROR_SC_0: #define IN_UNIT_ATTRS(X) \ &sensor_dev_attr_in##X##_input.dev_attr.attr, \ &sensor_dev_attr_in##X##_min.dev_attr.attr, \ - &sensor_dev_attr_in##X##_max.dev_attr.attr, \ + &sensor_dev_attr_in##X##_max.dev_attr.attr, \ &sensor_dev_attr_in##X##_alarm.dev_attr.attr, \ &sensor_dev_attr_in##X##_beep.dev_attr.attr @@ -1441,9 +1436,9 @@ w83781d_isa_remove(struct platform_device *pdev) } /* The SMBus locks itself, usually, but nothing may access the Winbond between - bank switches. ISA access must always be locked explicitly! + bank switches. ISA access must always be locked explicitly! We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, - would slow down the W83781D access and should not be necessary. + would slow down the W83781D access and should not be necessary. There are some ugly typecasts here, but the good news is - they should nowhere else be necessary! */ static int diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index efc74c0fda56..dc373e5eb262 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -101,7 +101,6 @@ #define I2C_DRIVERID_LM78 1002 #define I2C_DRIVERID_LM75 1003 #define I2C_DRIVERID_EEPROM 1005 -#define I2C_DRIVERID_W83781D 1006 #define I2C_DRIVERID_LM80 1007 #define I2C_DRIVERID_ADM1021 1008 #define I2C_DRIVERID_ADM9240 1009 From d5b0b5d62823f08ab4988e1b179fd5a9bddced31 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 14 Dec 2007 14:41:53 +0100 Subject: [PATCH 35/59] hwmon: (it87) Delete pwmN_freq files on driver removal In commit f8d0c19a93cea3a26a90f2462295e1e01a4cd250 I forgot to delete the pwmN_freq files on driver removal, here's the fix. Signed-off-by: Jean Delvare Acked-by: Riku Voipio Signed-off-by: Mark M. Hoffman --- drivers/hwmon/it87.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index ca0a723cbce5..e12c132ff83a 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -933,6 +933,9 @@ static struct attribute *it87_attributes_opt[] = { &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_pwm3.dev_attr.attr, + &dev_attr_pwm1_freq.attr, + &dev_attr_pwm2_freq.attr, + &dev_attr_pwm3_freq.attr, &dev_attr_vrm.attr, &dev_attr_cpu0_vid.attr, From 38a1f0e9aed014be66c474ecd9fe8513646de833 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 2 Dec 2007 23:32:42 +0100 Subject: [PATCH 36/59] hwmon: (adm1031) Fix register overwrite in set_fan_div() Don't rely on the register cache when setting a new fan clock divider. For one thing, the cache might not have been initialized at all if the driver has just been loaded. For another, the cached values may be old and you never know what can happen in the driver's back. Also invalidate the cache instead of trying to adjust the measured fan speed: the whole point of changing the clock divider is to get a better reading. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1031.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 37cfc101da5e..558d83b25b68 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -542,18 +542,26 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) return -EINVAL; mutex_lock(&data->update_lock); + /* Get fresh readings */ + data->fan_div[nr] = adm1031_read_value(client, + ADM1031_REG_FAN_DIV(nr)); + data->fan_min[nr] = adm1031_read_value(client, + ADM1031_REG_FAN_MIN(nr)); + + /* Write the new clock divider and fan min */ old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); new_min = data->fan_min[nr] * old_div / FAN_DIV_FROM_REG(data->fan_div[nr]); data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; - data->fan[nr] = data->fan[nr] * old_div / - FAN_DIV_FROM_REG(data->fan_div[nr]); adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), data->fan_div[nr]); adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); + + /* Invalidate the cache: fan speed is no longer valid */ + data->valid = 0; mutex_unlock(&data->update_lock); return count; } From 6d6006b8db5ead05053ccfbc45ab7e5c600a81b1 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 2 Dec 2007 23:33:57 +0100 Subject: [PATCH 37/59] hwmon: (adm1031) Various cleanups * Rename new_client to client * Drop redundant initializations to 0 * Drop trailing space * Other whitespace cleanups * Split/fold a few long lines * Constify static data * Optimizations in set_fan_div() Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1031.c | 126 ++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 64 deletions(-) diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 558d83b25b68..b3e358c65d02 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -5,7 +5,7 @@ Supports adm1030 / adm1031 Copyright (C) 2004 Alexandre d'Alton Reworked by Jean Delvare - + 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 @@ -32,22 +32,22 @@ /* Following macros takes channel parameter starting from 0 to 2 */ #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) -#define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) +#define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) #define ADM1031_REG_PWM (0x22) #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) -#define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4*(nr)) -#define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4*(nr)) -#define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4*(nr)) +#define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) +#define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) +#define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) -#define ADM1031_REG_TEMP(nr) (0xa + (nr)) +#define ADM1031_REG_TEMP(nr) (0x0a + (nr)) #define ADM1031_REG_AUTO_TEMP(nr) (0x24 + (nr)) #define ADM1031_REG_STATUS(nr) (0x2 + (nr)) -#define ADM1031_REG_CONF1 0x0 -#define ADM1031_REG_CONF2 0x1 -#define ADM1031_REG_EXT_TEMP 0x6 +#define ADM1031_REG_CONF1 0x00 +#define ADM1031_REG_CONF2 0x01 +#define ADM1031_REG_EXT_TEMP 0x06 #define ADM1031_CONF1_MONITOR_ENABLE 0x01 /* Monitoring enable */ #define ADM1031_CONF1_PWM_INVERT 0x08 /* PWM Invert */ @@ -78,7 +78,7 @@ struct adm1031_data { /* The chan_select_table contains the possible configurations for * auto fan control. */ - auto_chan_table_t *chan_select_table; + const auto_chan_table_t *chan_select_table; u16 alarm; u8 conf1; u8 conf2; @@ -181,25 +181,25 @@ static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm) #define GET_FAN_AUTO_BITFIELD(data, idx) \ (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2] -/* The tables below contains the possible values for the auto fan +/* The tables below contains the possible values for the auto fan * control bitfields. the index in the table is the register value. * MSb is the auto fan control enable bit, so the four first entries * in the table disables auto fan control when both bitfields are zero. */ -static auto_chan_table_t auto_channel_select_table_adm1031 = { - {0, 0}, {0, 0}, {0, 0}, {0, 0}, - {2 /*0b010 */ , 4 /*0b100 */ }, - {2 /*0b010 */ , 2 /*0b010 */ }, - {4 /*0b100 */ , 4 /*0b100 */ }, - {7 /*0b111 */ , 7 /*0b111 */ }, +static const auto_chan_table_t auto_channel_select_table_adm1031 = { + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 2 /* 0b010 */ , 4 /* 0b100 */ }, + { 2 /* 0b010 */ , 2 /* 0b010 */ }, + { 4 /* 0b100 */ , 4 /* 0b100 */ }, + { 7 /* 0b111 */ , 7 /* 0b111 */ }, }; -static auto_chan_table_t auto_channel_select_table_adm1030 = { - {0, 0}, {0, 0}, {0, 0}, {0, 0}, - {2 /*0b10 */ , 0}, - {0xff /*invalid */ , 0}, - {0xff /*invalid */ , 0}, - {3 /*0b11 */ , 0}, +static const auto_chan_table_t auto_channel_select_table_adm1030 = { + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 2 /* 0b10 */ , 0 }, + { 0xff /* invalid */ , 0 }, + { 0xff /* invalid */ , 0 }, + { 3 /* 0b11 */ , 0 }, }; /* That function checks if a bitfield is valid and returns the other bitfield @@ -228,8 +228,8 @@ get_fan_auto_nearest(struct adm1031_data *data, break; } else if (val == (*data->chan_select_table)[i][chan] && first_match == -1) { - /* Save the first match in case of an exact match has not been - * found + /* Save the first match in case of an exact match has + * not been found */ first_match = i; } @@ -264,16 +264,17 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) old_fan_mode = data->conf1; mutex_lock(&data->update_lock); - + if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®))) { mutex_unlock(&data->update_lock); return ret; } - if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ + data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); + if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^ (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { if (data->conf1 & ADM1031_CONF1_AUTO_MODE){ - /* Switch to Auto Fan Mode - * Save PWM registers + /* Switch to Auto Fan Mode + * Save PWM registers * Set PWM registers to 33% Both */ data->old_pwm[0] = data->pwm[0]; data->old_pwm[1] = data->pwm[1]; @@ -283,7 +284,7 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) data->pwm[0] = data->old_pwm[0]; data->pwm[1] = data->old_pwm[1]; /* Restore PWM registers */ - adm1031_write_value(client, ADM1031_REG_PWM, + adm1031_write_value(client, ADM1031_REG_PWM, data->pwm[0] | (data->pwm[1] << 4)); } } @@ -314,7 +315,7 @@ fan_auto_channel_offset(2); static ssize_t show_auto_temp_off(struct device *dev, char *buf, int nr) { struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", + return sprintf(buf, "%d\n", AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); } static ssize_t show_auto_temp_min(struct device *dev, char *buf, int nr) @@ -407,7 +408,7 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr) int reg; mutex_lock(&data->update_lock); - if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && + if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && (((val>>4) & 0xf) != 5)) { /* In automatic mode, the only PWM accepted is 33% */ mutex_unlock(&data->update_lock); @@ -471,7 +472,7 @@ static int trust_fan_readings(struct adm1031_data *data, int chan) AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0]) || data->temp[1] >= AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]) - || (data->chip_type == adm1031 + || (data->chip_type == adm1031 && data->temp[2] >= AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2])); break; @@ -514,7 +515,7 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr) mutex_lock(&data->update_lock); if (val) { - data->fan_min[nr] = + data->fan_min[nr] = FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); } else { data->fan_min[nr] = 0xff; @@ -535,12 +536,12 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) tmp = val == 8 ? 0xc0 : val == 4 ? 0x80 : - val == 2 ? 0x40 : - val == 1 ? 0x00 : + val == 2 ? 0x40 : + val == 1 ? 0x00 : 0xff; if (tmp == 0xff) return -EINVAL; - + mutex_lock(&data->update_lock); /* Get fresh readings */ data->fan_div[nr] = adm1031_read_value(client, @@ -550,14 +551,13 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) /* Write the new clock divider and fan min */ old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); - data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); - new_min = data->fan_min[nr] * old_div / - FAN_DIV_FROM_REG(data->fan_div[nr]); + data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]); + new_min = data->fan_min[nr] * old_div / val; data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; - adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), + adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), data->fan_div[nr]); - adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), + adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); /* Invalidate the cache: fan speed is no longer valid */ @@ -796,7 +796,7 @@ static const struct attribute_group adm1031_group_opt = { /* This function is called by i2c_probe */ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *new_client; + struct i2c_client *client; struct adm1031_data *data; int err = 0; const char *name = ""; @@ -809,17 +809,16 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &adm1031_driver; - new_client->flags = 0; + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1031_driver; if (kind < 0) { int id, co; - id = i2c_smbus_read_byte_data(new_client, 0x3d); - co = i2c_smbus_read_byte_data(new_client, 0x3e); + id = i2c_smbus_read_byte_data(client, 0x3d); + co = i2c_smbus_read_byte_data(client, 0x3e); if (!((id == 0x31 || id == 0x30) && co == 0x41)) goto exit_free; @@ -840,28 +839,27 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) } data->chip_type = kind; - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; + strlcpy(client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto exit_free; /* Initialize the ADM1031 chip */ - adm1031_init_client(new_client); + adm1031_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1031_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group))) goto exit_detach; if (kind == adm1031) { - if ((err = sysfs_create_group(&new_client->dev.kobj, + if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt))) goto exit_remove; } - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exit_remove; @@ -870,10 +868,10 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_remove: - sysfs_remove_group(&new_client->dev.kobj, &adm1031_group); - sysfs_remove_group(&new_client->dev.kobj, &adm1031_group_opt); + sysfs_remove_group(&client->dev.kobj, &adm1031_group); + sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); exit_detach: - i2c_detach_client(new_client); + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -905,7 +903,7 @@ static void adm1031_init_client(struct i2c_client *client) if (data->chip_type == adm1031) { mask |= (ADM1031_CONF2_PWM2_ENABLE | ADM1031_CONF2_TACH2_ENABLE); - } + } /* Initialize the ADM1031 chip (enables fan speed reading ) */ read_val = adm1031_read_value(client, ADM1031_REG_CONF2); if ((read_val | mask) != read_val) { @@ -984,7 +982,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) if (data->chip_type == adm1030) { data->alarm &= 0xc0ff; } - + for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) { data->fan_div[chan] = adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan)); @@ -993,7 +991,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) data->fan[chan] = adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan)); data->pwm[chan] = - 0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >> + 0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >> (4*chan)); } data->last_updated = jiffies; From c801082d7d41928b2348507ecdc841d5ebad3490 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 2 Dec 2007 23:39:38 +0100 Subject: [PATCH 38/59] hwmon: (adm1031) Get rid of macro-generated wrappers Use the standard dynamic sysfs callbacks instead of macro-generated wrappers. It makes the code more simple and the binary smaller (-8% on my system.) Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1031.c | 319 ++++++++++++++++------------------------ 1 file changed, 129 insertions(+), 190 deletions(-) diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index b3e358c65d02..53210555441a 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -245,17 +246,21 @@ get_fan_auto_nearest(struct adm1031_data *data, return 0; } -static ssize_t show_fan_auto_channel(struct device *dev, char *buf, int nr) +static ssize_t show_fan_auto_channel(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr)); } static ssize_t -set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) +set_fan_auto_channel(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val = simple_strtol(buf, NULL, 10); u8 reg; int ret; @@ -294,41 +299,35 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) return count; } -#define fan_auto_channel_offset(offset) \ -static ssize_t show_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_auto_channel(dev, buf, offset - 1); \ -} \ -static ssize_t set_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_fan_auto_channel(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(auto_fan##offset##_channel, S_IRUGO | S_IWUSR, \ - show_fan_auto_channel_##offset, \ - set_fan_auto_channel_##offset) - -fan_auto_channel_offset(1); -fan_auto_channel_offset(2); +static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR, + show_fan_auto_channel, set_fan_auto_channel, 0); +static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR, + show_fan_auto_channel, set_fan_auto_channel, 1); /* Auto Temps */ -static ssize_t show_auto_temp_off(struct device *dev, char *buf, int nr) +static ssize_t show_auto_temp_off(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); } -static ssize_t show_auto_temp_min(struct device *dev, char *buf, int nr) +static ssize_t show_auto_temp_min(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])); } static ssize_t -set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr) +set_auto_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -338,17 +337,21 @@ set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr) mutex_unlock(&data->update_lock); return count; } -static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr) +static ssize_t show_auto_temp_max(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])); } static ssize_t -set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr) +set_auto_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -359,51 +362,32 @@ set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr) return count; } -#define auto_temp_reg(offset) \ -static ssize_t show_auto_temp_##offset##_off (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_auto_temp_off(dev, buf, offset - 1); \ -} \ -static ssize_t show_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_auto_temp_min(dev, buf, offset - 1); \ -} \ -static ssize_t show_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_auto_temp_max(dev, buf, offset - 1); \ -} \ -static ssize_t set_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_auto_temp_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_auto_temp_max(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO, \ - show_auto_temp_##offset##_off, NULL); \ -static DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_auto_temp_##offset##_min, set_auto_temp_##offset##_min);\ -static DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_auto_temp_##offset##_max, set_auto_temp_##offset##_max) +#define auto_temp_reg(offset) \ +static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO, \ + show_auto_temp_off, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR, \ + show_auto_temp_min, set_auto_temp_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR, \ + show_auto_temp_max, set_auto_temp_max, offset - 1) auto_temp_reg(1); auto_temp_reg(2); auto_temp_reg(3); /* pwm */ -static ssize_t show_pwm(struct device *dev, char *buf, int nr) +static ssize_t show_pwm(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); } -static ssize_t -set_pwm(struct device *dev, const char *buf, size_t count, int nr) +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val = simple_strtol(buf, NULL, 10); int reg; @@ -423,21 +407,12 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr) return count; } -#define pwm_reg(offset) \ -static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_pwm(dev, buf, offset - 1); \ -} \ -static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_pwm(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_pwm_##offset, set_pwm_##offset) - -pwm_reg(1); -pwm_reg(2); +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR, + show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR, + show_pwm, set_pwm, 1); /* Fans */ @@ -484,8 +459,10 @@ static int trust_fan_readings(struct adm1031_data *data, int chan) } -static ssize_t show_fan(struct device *dev, char *buf, int nr) +static ssize_t show_fan(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); int value; @@ -494,23 +471,28 @@ static ssize_t show_fan(struct device *dev, char *buf, int nr) return sprintf(buf, "%d\n", value); } -static ssize_t show_fan_div(struct device *dev, char *buf, int nr) +static ssize_t show_fan_div(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr])); } -static ssize_t show_fan_min(struct device *dev, char *buf, int nr) +static ssize_t show_fan_min(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], FAN_DIV_FROM_REG(data->fan_div[nr]))); } -static ssize_t -set_fan_min(struct device *dev, const char *buf, size_t count, int nr) +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -524,11 +506,12 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr) mutex_unlock(&data->update_lock); return count; } -static ssize_t -set_fan_div(struct device *dev, const char *buf, size_t count, int nr) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val = simple_strtol(buf, NULL, 10); u8 tmp; int old_div; @@ -567,44 +550,22 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) } #define fan_offset(offset) \ -static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_min(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_div(dev, buf, offset - 1); \ -} \ -static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_fan_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_fan_div(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, \ - NULL); \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min); \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_div, set_fan_##offset##_div); \ -static DEVICE_ATTR(auto_fan##offset##_min_pwm, S_IRUGO | S_IWUSR, \ - show_pwm_##offset, set_pwm_##offset) +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_min, set_fan_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ + show_fan_div, set_fan_div, offset - 1) fan_offset(1); fan_offset(2); /* Temps */ -static ssize_t show_temp(struct device *dev, char *buf, int nr) +static ssize_t show_temp(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); int ext; ext = nr == 0 ? @@ -612,26 +573,33 @@ static ssize_t show_temp(struct device *dev, char *buf, int nr) (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); } -static ssize_t show_temp_min(struct device *dev, char *buf, int nr) +static ssize_t show_temp_min(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); } -static ssize_t show_temp_max(struct device *dev, char *buf, int nr) +static ssize_t show_temp_max(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); } -static ssize_t show_temp_crit(struct device *dev, char *buf, int nr) +static ssize_t show_temp_crit(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); } -static ssize_t -set_temp_min(struct device *dev, const char *buf, size_t count, int nr) +static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val; val = simple_strtol(buf, NULL, 10); @@ -643,11 +611,12 @@ set_temp_min(struct device *dev, const char *buf, size_t count, int nr) mutex_unlock(&data->update_lock); return count; } -static ssize_t -set_temp_max(struct device *dev, const char *buf, size_t count, int nr) +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val; val = simple_strtol(buf, NULL, 10); @@ -659,11 +628,12 @@ set_temp_max(struct device *dev, const char *buf, size_t count, int nr) mutex_unlock(&data->update_lock); return count; } -static ssize_t -set_temp_crit(struct device *dev, const char *buf, size_t count, int nr) +static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); + int nr = to_sensor_dev_attr(attr)->index; int val; val = simple_strtol(buf, NULL, 10); @@ -676,46 +646,15 @@ set_temp_crit(struct device *dev, const char *buf, size_t count, int nr) return count; } -#define temp_reg(offset) \ -static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp(dev, buf, offset - 1); \ -} \ -static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_min(dev, buf, offset - 1); \ -} \ -static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_max(dev, buf, offset - 1); \ -} \ -static ssize_t show_temp_##offset##_crit (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_crit(dev, buf, offset - 1); \ -} \ -static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_max(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_temp_##offset##_crit (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_crit(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, \ - NULL); \ -static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_min, set_temp_##offset##_min); \ -static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_max, set_temp_##offset##_max); \ -static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_crit, set_temp_##offset##_crit) +#define temp_reg(offset) \ +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ + show_temp, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ + show_temp_min, set_temp_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ + show_temp_crit, set_temp_crit, offset - 1) temp_reg(1); temp_reg(2); @@ -739,29 +678,29 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter) } static struct attribute *adm1031_attributes[] = { - &dev_attr_fan1_input.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan1_min.attr, - &dev_attr_pwm1.attr, - &dev_attr_auto_fan1_channel.attr, - &dev_attr_temp1_input.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_crit.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp2_min.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp2_crit.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, + &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_crit.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_crit.dev_attr.attr, - &dev_attr_auto_temp1_off.attr, - &dev_attr_auto_temp1_min.attr, - &dev_attr_auto_temp1_max.attr, + &sensor_dev_attr_auto_temp1_off.dev_attr.attr, + &sensor_dev_attr_auto_temp1_min.dev_attr.attr, + &sensor_dev_attr_auto_temp1_max.dev_attr.attr, - &dev_attr_auto_temp2_off.attr, - &dev_attr_auto_temp2_min.attr, - &dev_attr_auto_temp2_max.attr, + &sensor_dev_attr_auto_temp2_off.dev_attr.attr, + &sensor_dev_attr_auto_temp2_min.dev_attr.attr, + &sensor_dev_attr_auto_temp2_max.dev_attr.attr, - &dev_attr_auto_fan1_min_pwm.attr, + &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, &dev_attr_alarms.attr, @@ -773,19 +712,19 @@ static const struct attribute_group adm1031_group = { }; static struct attribute *adm1031_attributes_opt[] = { - &dev_attr_fan2_input.attr, - &dev_attr_fan2_div.attr, - &dev_attr_fan2_min.attr, - &dev_attr_pwm2.attr, - &dev_attr_auto_fan2_channel.attr, - &dev_attr_temp3_input.attr, - &dev_attr_temp3_min.attr, - &dev_attr_temp3_max.attr, - &dev_attr_temp3_crit.attr, - &dev_attr_auto_temp3_off.attr, - &dev_attr_auto_temp3_min.attr, - &dev_attr_auto_temp3_max.attr, - &dev_attr_auto_fan2_min_pwm.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_auto_fan2_channel.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_crit.dev_attr.attr, + &sensor_dev_attr_auto_temp3_off.dev_attr.attr, + &sensor_dev_attr_auto_temp3_min.dev_attr.attr, + &sensor_dev_attr_auto_temp3_max.dev_attr.attr, + &sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr, NULL }; From 050ab8789869eabb6b2e066aca0d13d86013c315 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 2 Dec 2007 23:42:24 +0100 Subject: [PATCH 39/59] hwmon: (adm1031) Add individual alarm and fault files The new libsensors needs these. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1031.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 53210555441a..5aaad3636c98 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -669,6 +669,29 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_alarm(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct adm1031_data *data = adm1031_update_device(dev); + return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1); +} + +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); static int adm1031_attach_adapter(struct i2c_adapter *adapter) { @@ -681,16 +704,25 @@ static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, &sensor_dev_attr_temp2_crit.dev_attr.attr, + &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_auto_temp1_off.dev_attr.attr, &sensor_dev_attr_auto_temp1_min.dev_attr.attr, @@ -715,12 +747,18 @@ static struct attribute *adm1031_attributes_opt[] = { &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, &sensor_dev_attr_temp3_crit.dev_attr.attr, + &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, &sensor_dev_attr_auto_temp3_off.dev_attr.attr, &sensor_dev_attr_auto_temp3_min.dev_attr.attr, &sensor_dev_attr_auto_temp3_max.dev_attr.attr, From 4b4df95dccdd2c6a573c9dedefb747ed663c074d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 3 Dec 2007 23:23:21 +0100 Subject: [PATCH 40/59] hwmon: (lm85) Return standard values in pwmN_enable The values returned by the lm85 driver in pwmN_enable sysfs files do not match the standard. Fix that. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm85.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index a02480be65f2..194b8fb52f0e 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -519,10 +519,21 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute { int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); - int pwm_zone; + int pwm_zone, enable; pwm_zone = ZONE_FROM_REG(data->autofan[nr].config); - return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) ); + switch (pwm_zone) { + case -1: /* PWM is always at 100% */ + enable = 0; + break; + case 0: /* PWM is always at 0% */ + case -2: /* PWM responds to manual control */ + enable = 1; + break; + default: /* PWM in automatic mode */ + enable = 2; + } + return sprintf(buf, "%d\n", enable); } #define show_pwm_reg(offset) \ From 455f791ea3e33a274c098b4a8c2e35d4d1a6d518 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 3 Dec 2007 23:28:42 +0100 Subject: [PATCH 41/59] hwmon: (lm85) Make the pwmN_enable files writable Make the pwmN_enable files writable. This makes it possible to use standard fan speed control tools (pwmconfig, fancontrol) with the lm85 driver. I left the non-standard pwmN_auto_channels files in place, as they give additional control for the automatic mode, and some users might be used to them by now. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm85.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 194b8fb52f0e..9f1c6f1ee035 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -536,11 +536,47 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", enable); } +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + u8 config; + + switch (val) { + case 0: + config = 3; + break; + case 1: + config = 7; + break; + case 2: + /* Here we have to choose arbitrarily one of the 5 possible + configurations; I go for the safest */ + config = 6; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + data->autofan[nr].config = lm85_read_value(client, + LM85_REG_AFAN_CONFIG(nr)); + data->autofan[nr].config = (data->autofan[nr].config & ~0xe0) + | (config << 5); + lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), + data->autofan[nr].config); + mutex_unlock(&data->update_lock); + return count; +} + #define show_pwm_reg(offset) \ static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ show_pwm, set_pwm, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO, \ - show_pwm_enable, NULL, offset - 1) +static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ + show_pwm_enable, set_pwm_enable, offset - 1) show_pwm_reg(1); show_pwm_reg(2); From 7b501b1f53605bec17454dd8bbdbbf3f57a7cf32 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 19:44:09 +0100 Subject: [PATCH 42/59] hwmon: Discard useless I2C driver IDs Many I2C hwmon drivers define a driver ID but no other code references these, meaning that they are useless. Discard them, along with a few IDs which are defined but never used at all. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1021.c | 1 - drivers/hwmon/adm1025.c | 1 - drivers/hwmon/adm9240.c | 1 - drivers/hwmon/asb100.c | 1 - drivers/hwmon/ds1621.c | 1 - drivers/hwmon/fscher.c | 1 - drivers/hwmon/fscpos.c | 1 - drivers/hwmon/lm75.c | 1 - drivers/hwmon/lm78.c | 1 - drivers/hwmon/lm80.c | 1 - drivers/hwmon/lm83.c | 1 - drivers/hwmon/lm85.c | 1 - drivers/hwmon/lm87.c | 1 - drivers/hwmon/lm90.c | 1 - drivers/hwmon/lm92.c | 1 - drivers/hwmon/w83l785ts.c | 1 - drivers/i2c/chips/eeprom.c | 1 - drivers/i2c/chips/pcf8574.c | 1 - drivers/i2c/chips/pcf8591.c | 1 - include/linux/i2c-id.h | 33 --------------------------------- 20 files changed, 52 deletions(-) diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index ebdc6d7db231..b96be772e498 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -115,7 +115,6 @@ static struct i2c_driver adm1021_driver = { .driver = { .name = "adm1021", }, - .id = I2C_DRIVERID_ADM1021, .attach_adapter = adm1021_attach_adapter, .detach_client = adm1021_detach_client, }; diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index c7a365a9e405..33cc58b2fadb 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -123,7 +123,6 @@ static struct i2c_driver adm1025_driver = { .driver = { .name = "adm1025", }, - .id = I2C_DRIVERID_ADM1025, .attach_adapter = adm1025_attach_adapter, .detach_client = adm1025_detach_client, }; diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index c17d0b6b3283..7887192c4236 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -141,7 +141,6 @@ static struct i2c_driver adm9240_driver = { .driver = { .name = "adm9240", }, - .id = I2C_DRIVERID_ADM9240, .attach_adapter = adm9240_attach_adapter, .detach_client = adm9240_detach_client, }; diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 9460dba4cf74..815493b9788d 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -221,7 +221,6 @@ static struct i2c_driver asb100_driver = { .driver = { .name = "asb100", }, - .id = I2C_DRIVERID_ASB100, .attach_adapter = asb100_attach_adapter, .detach_client = asb100_detach_client, }; diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index b7bd000b130f..3f5163de13c1 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -94,7 +94,6 @@ static struct i2c_driver ds1621_driver = { .driver = { .name = "ds1621", }, - .id = I2C_DRIVERID_DS1621, .attach_adapter = ds1621_attach_adapter, .detach_client = ds1621_detach_client, }; diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index e67c36953b2d..721c70177b17 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c @@ -123,7 +123,6 @@ static struct i2c_driver fscher_driver = { .driver = { .name = "fscher", }, - .id = I2C_DRIVERID_FSCHER, .attach_adapter = fscher_attach_adapter, .detach_client = fscher_detach_client, }; diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 92c9703d0ac0..2f1075323a1e 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -105,7 +105,6 @@ static struct i2c_driver fscpos_driver = { .driver = { .name = "fscpos", }, - .id = I2C_DRIVERID_FSCPOS, .attach_adapter = fscpos_attach_adapter, .detach_client = fscpos_detach_client, }; diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 37a8cc032ffa..e5c35a355a57 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -74,7 +74,6 @@ static struct i2c_driver lm75_driver = { .driver = { .name = "lm75", }, - .id = I2C_DRIVERID_LM75, .attach_adapter = lm75_attach_adapter, .detach_client = lm75_detach_client, }; diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 934378eb4f8f..0a9eb1f6f4e4 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -168,7 +168,6 @@ static struct i2c_driver lm78_driver = { .driver = { .name = "lm78", }, - .id = I2C_DRIVERID_LM78, .attach_adapter = lm78_attach_adapter, .detach_client = lm78_detach_client, }; diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 063cdba00a88..0bde0a382ef1 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -147,7 +147,6 @@ static struct i2c_driver lm80_driver = { .driver = { .name = "lm80", }, - .id = I2C_DRIVERID_LM80, .attach_adapter = lm80_attach_adapter, .detach_client = lm80_detach_client, }; diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 0336b4572a61..6e8903a6e902 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -133,7 +133,6 @@ static struct i2c_driver lm83_driver = { .driver = { .name = "lm83", }, - .id = I2C_DRIVERID_LM83, .attach_adapter = lm83_attach_adapter, .detach_client = lm83_detach_client, }; diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 9f1c6f1ee035..43212db7c798 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -367,7 +367,6 @@ static struct i2c_driver lm85_driver = { .driver = { .name = "lm85", }, - .id = I2C_DRIVERID_LM85, .attach_adapter = lm85_attach_adapter, .detach_client = lm85_detach_client, }; diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 3ab4c3f0efdd..7bedf7455e9a 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -171,7 +171,6 @@ static struct i2c_driver lm87_driver = { .driver = { .name = "lm87", }, - .id = I2C_DRIVERID_LM87, .attach_adapter = lm87_attach_adapter, .detach_client = lm87_detach_client, }; diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 116093d0eb3e..f7ec95bedbf6 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -204,7 +204,6 @@ static struct i2c_driver lm90_driver = { .driver = { .name = "lm90", }, - .id = I2C_DRIVERID_LM90, .attach_adapter = lm90_attach_adapter, .detach_client = lm90_detach_client, }; diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index 61d1bd1d5b6e..af5c77d568fe 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -428,7 +428,6 @@ static struct i2c_driver lm92_driver = { .driver = { .name = "lm92", }, - .id = I2C_DRIVERID_LM92, .attach_adapter = lm92_attach_adapter, .detach_client = lm92_detach_client, }; diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index b5db354e2f19..1d6259d29e74 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -96,7 +96,6 @@ static struct i2c_driver w83l785ts_driver = { .driver = { .name = "w83l785ts", }, - .id = I2C_DRIVERID_W83L785TS, .attach_adapter = w83l785ts_attach_adapter, .detach_client = w83l785ts_detach_client, }; diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index fde297b21ad7..7dee001e5133 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -71,7 +71,6 @@ static struct i2c_driver eeprom_driver = { .driver = { .name = "eeprom", }, - .id = I2C_DRIVERID_EEPROM, .attach_adapter = eeprom_attach_adapter, .detach_client = eeprom_detach_client, }; diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c index b3b830ccf209..e5b31329b56e 100644 --- a/drivers/i2c/chips/pcf8574.c +++ b/drivers/i2c/chips/pcf8574.c @@ -67,7 +67,6 @@ static struct i2c_driver pcf8574_driver = { .driver = { .name = "pcf8574", }, - .id = I2C_DRIVERID_PCF8574, .attach_adapter = pcf8574_attach_adapter, .detach_client = pcf8574_detach_client, }; diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index 865f4409c06b..66c7c3bb9429 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c @@ -92,7 +92,6 @@ static struct i2c_driver pcf8591_driver = { .driver = { .name = "pcf8591", }, - .id = I2C_DRIVERID_PCF8591, .attach_adapter = pcf8591_attach_adapter, .detach_client = pcf8591_detach_client, }; diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index dc373e5eb262..b979112f74e0 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -96,39 +96,6 @@ #define I2C_DRIVERID_I2CDEV 900 -/* IDs -- Use DRIVERIDs 1000-1999 for sensors. - These were originally in sensors.h in the lm_sensors package */ -#define I2C_DRIVERID_LM78 1002 -#define I2C_DRIVERID_LM75 1003 -#define I2C_DRIVERID_EEPROM 1005 -#define I2C_DRIVERID_LM80 1007 -#define I2C_DRIVERID_ADM1021 1008 -#define I2C_DRIVERID_ADM9240 1009 -#define I2C_DRIVERID_LTC1710 1010 -#define I2C_DRIVERID_BT869 1013 -#define I2C_DRIVERID_MAXILIFE 1014 -#define I2C_DRIVERID_MATORB 1015 -#define I2C_DRIVERID_THMC50 1017 -#define I2C_DRIVERID_ADM1025 1020 -#define I2C_DRIVERID_LM87 1021 -#define I2C_DRIVERID_PCF8574 1022 -#define I2C_DRIVERID_MTP008 1023 -#define I2C_DRIVERID_DS1621 1024 -#define I2C_DRIVERID_ADM1024 1025 -#define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */ -#define I2C_DRIVERID_FSCPOS 1028 -#define I2C_DRIVERID_FSCSCY 1029 -#define I2C_DRIVERID_PCF8591 1030 -#define I2C_DRIVERID_LM92 1033 -#define I2C_DRIVERID_SMARTBATT 1035 -#define I2C_DRIVERID_BMCSENSORS 1036 -#define I2C_DRIVERID_FS451 1037 -#define I2C_DRIVERID_LM85 1039 -#define I2C_DRIVERID_LM83 1040 -#define I2C_DRIVERID_LM90 1042 -#define I2C_DRIVERID_ASB100 1043 -#define I2C_DRIVERID_FSCHER 1046 -#define I2C_DRIVERID_W83L785TS 1047 #define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */ /* From 1f52af0f6940dd4ab96edb9bbc56012ecc6c67e0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 23:35:33 +0100 Subject: [PATCH 43/59] hwmon: (lm77) Add individual alarm files The new libsensors needs this. As the old library never had support for the lm77 driver, I even dropped the legacy "alarms" file. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm77.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index cee5c2e8cfad..459b70ad6bee 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -113,7 +114,6 @@ show(temp_input); show(temp_crit); show(temp_min); show(temp_max); -show(alarms); /* read routines for hysteresis values */ static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf) @@ -186,6 +186,14 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct lm77_data *data = lm77_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} + static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, @@ -202,8 +210,9 @@ static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp_max_hyst, NULL); -static DEVICE_ATTR(alarms, S_IRUGO, - show_alarms, NULL); +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); static int lm77_attach_adapter(struct i2c_adapter *adapter) { @@ -220,8 +229,9 @@ static struct attribute *lm77_attributes[] = { &dev_attr_temp1_crit_hyst.attr, &dev_attr_temp1_min_hyst.attr, &dev_attr_temp1_max_hyst.attr, - &dev_attr_alarms.attr, - + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, NULL }; From 360f9452def0be1d6e29cee07a0f0640cd1d7b22 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 6 Jan 2008 15:49:19 +0100 Subject: [PATCH 44/59] hwmon: (adm9240) Add individual alarm files The new libsensors needs these individual alarm files. Signed-off-by: Jean Delvare Tested-by: Grant Coady Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm9240.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 7887192c4236..7671d2bf7800 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -414,6 +414,23 @@ static ssize_t show_alarms(struct device *dev, } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_alarm(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); + /* vid */ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) @@ -468,30 +485,39 @@ static struct attribute *adm9240_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in5_min.dev_attr.attr, &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, &dev_attr_temp1_input.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_aout_output.attr, &dev_attr_chassis_clear.attr, From 5812f9283e621370a2d65282b7bcc942bf2c3f1c Mon Sep 17 00:00:00 2001 From: Steve Hardy Date: Tue, 22 Jan 2008 23:00:02 +0000 Subject: [PATCH 45/59] hwmon: Add support for Texas Instruments/Burr-Brown ADS7828 Signed-off-by: Steve Hardy Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/ads7828 | 36 +++++ drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/ads7828.c | 297 ++++++++++++++++++++++++++++++++++++ 4 files changed, 344 insertions(+) create mode 100644 Documentation/hwmon/ads7828 create mode 100644 drivers/hwmon/ads7828.c diff --git a/Documentation/hwmon/ads7828 b/Documentation/hwmon/ads7828 new file mode 100644 index 000000000000..75bc4beaf447 --- /dev/null +++ b/Documentation/hwmon/ads7828 @@ -0,0 +1,36 @@ +Kernel driver ads7828 +===================== + +Supported chips: + * Texas Instruments/Burr-Brown ADS7828 + Prefix: 'ads7828' + Addresses scanned: I2C 0x48, 0x49, 0x4a, 0x4b + Datasheet: Publicly available at the Texas Instruments website : + http://focus.ti.com/lit/ds/symlink/ads7828.pdf + +Authors: + Steve Hardy + +Module Parameters +----------------- + +* se_input: bool (default Y) + Single ended operation - set to N for differential mode +* int_vref: bool (default Y) + Operate with the internal 2.5V reference - set to N for external reference +* vref_mv: int (default 2500) + If using an external reference, set this to the reference voltage in mV + +Description +----------- + +This driver implements support for the Texas Instruments ADS7828. + +This device is a 12-bit 8-channel A-D converter. + +It can operate in single ended mode (8 +ve inputs) or in differential mode, +where 4 differential pairs can be measured. + +The chip also has the facility to use an external voltage reference. This +may be required if your hardware supplies the ADS7828 from a 5V supply, see +the datasheet for more details. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 27e0b34ead5f..410ffe4e9d80 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -588,6 +588,16 @@ config SENSORS_SMSC47B397 This driver can also be built as a module. If so, the module will be called smsc47b397. +config SENSORS_ADS7828 + tristate "Texas Instruments ADS7828" + depends on I2C + help + If you say yes here you get support for Texas Instruments ADS7828 + 12-bit 8-channel ADC device. + + This driver can also be built as a module. If so, the module + will be called ads7828. + config SENSORS_THMC50 tristate "Texas Instruments THMC50 / Analog Devices ADM1022" depends on I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 77a3e093c247..824161337f1c 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o +obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o obj-$(CONFIG_SENSORS_AMS) += ams/ diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c new file mode 100644 index 000000000000..6b8a73ef404c --- /dev/null +++ b/drivers/hwmon/ads7828.c @@ -0,0 +1,297 @@ +/* + ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC + (C) 2007 EADS Astrium + + This driver is based on the lm75 and other lm_sensors/hwmon drivers + + Written by Steve Hardy + + Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf + + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* The ADS7828 registers */ +#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */ +#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */ +#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */ +#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */ +#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */ +#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */ +#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */ +#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */ + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, + I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(ads7828); + +/* Other module parameters */ +static int se_input = 1; /* Default is SE, 0 == diff */ +static int int_vref = 1; /* Default is internal ref ON */ +static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */ +module_param(se_input, bool, S_IRUGO); +module_param(int_vref, bool, S_IRUGO); +module_param(vref_mv, int, S_IRUGO); + +/* Global Variables */ +static u8 ads7828_cmd_byte; /* cmd byte without channel bits */ +static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */ + +/* Each client has this additional data */ +struct ads7828_data { + struct i2c_client client; + struct device *hwmon_dev; + struct mutex update_lock; /* mutex protect updates */ + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */ +}; + +/* Function declaration - necessary due to function dependencies */ +static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind); + +/* The ADS7828 returns the 12-bit sample in two bytes, + these are read as a word then byte-swapped */ +static u16 ads7828_read_value(struct i2c_client *client, u8 reg) +{ + return swab16(i2c_smbus_read_word_data(client, reg)); +} + +static inline u8 channel_cmd_byte(int ch) +{ + /* cmd byte C2,C1,C0 - see datasheet */ + u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4); + cmd |= ads7828_cmd_byte; + return cmd; +} + +/* Update data for the device (all 8 channels) */ +static struct ads7828_data *ads7828_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ads7828_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + unsigned int ch; + dev_dbg(&client->dev, "Starting ads7828 update\n"); + + for (ch = 0; ch < ADS7828_NCH; ch++) { + u8 cmd = channel_cmd_byte(ch); + data->adc_input[ch] = ads7828_read_value(client, cmd); + } + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* sysfs callback function */ +static ssize_t show_in(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ads7828_data *data = ads7828_update_device(dev); + /* Print value (in mV as specified in sysfs-interface documentation) */ + return sprintf(buf, "%d\n", (data->adc_input[attr->index] * + ads7828_lsb_resol)/1000); +} + +#define in_reg(offset)\ +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\ + NULL, offset) + +in_reg(0); +in_reg(1); +in_reg(2); +in_reg(3); +in_reg(4); +in_reg(5); +in_reg(6); +in_reg(7); + +static struct attribute *ads7828_attributes[] = { + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group ads7828_group = { + .attrs = ads7828_attributes, +}; + +static int ads7828_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, ads7828_detect); +} + +static int ads7828_detach_client(struct i2c_client *client) +{ + struct ads7828_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ads7828_group); + i2c_detach_client(client); + kfree(i2c_get_clientdata(client)); + return 0; +} + +/* This is the driver that will be inserted */ +static struct i2c_driver ads7828_driver = { + .driver = { + .name = "ads7828", + }, + .attach_adapter = ads7828_attach_adapter, + .detach_client = ads7828_detach_client, +}; + +/* This function is called by i2c_probe */ +static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct ads7828_data *data; + int err = 0; + const char *name = ""; + + /* Check we have a valid client */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) + goto exit; + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access ads7828_read_value. */ + data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &ads7828_driver; + + /* Now, we do the remaining detection. There is no identification + dedicated register so attempt to sanity check using knowledge of + the chip + - Read from the 8 channel addresses + - Check the top 4 bits of each result are not set (12 data bits) + */ + if (kind < 0) { + int ch; + for (ch = 0; ch < ADS7828_NCH; ch++) { + u16 in_data; + u8 cmd = channel_cmd_byte(ch); + in_data = ads7828_read_value(client, cmd); + if (in_data & 0xF000) { + printk(KERN_DEBUG + "%s : Doesn't look like an ads7828 device\n", + __FUNCTION__); + goto exit_free; + } + } + } + + /* Determine the chip type - only one kind supported! */ + if (kind <= 0) + kind = ads7828; + + if (kind == ads7828) + name = "ads7828"; + + /* Fill in the remaining client fields, put it into the global list */ + strlcpy(client->name, name, I2C_NAME_SIZE); + + mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + err = i2c_attach_client(client); + if (err) + goto exit_free; + + /* Register sysfs hooks */ + err = sysfs_create_group(&client->dev.kobj, &ads7828_group); + if (err) + goto exit_detach; + + 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, &ads7828_group); +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int __init sensors_ads7828_init(void) +{ + /* Initialize the command byte according to module parameters */ + ads7828_cmd_byte = se_input ? + ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF; + ads7828_cmd_byte |= int_vref ? + ADS7828_CMD_PD3 : ADS7828_CMD_PD1; + + /* Calculate the LSB resolution */ + ads7828_lsb_resol = (vref_mv*1000)/4096; + + return i2c_add_driver(&ads7828_driver); +} + +static void __exit sensors_ads7828_exit(void) +{ + i2c_del_driver(&ads7828_driver); +} + +MODULE_AUTHOR("Steve Hardy "); +MODULE_DESCRIPTION("ADS7828 driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_ads7828_init); +module_exit(sensors_ads7828_exit); From cb96b8ca11644ee1223e0fb3f1f629ead15203cb Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Tue, 15 Jan 2008 21:57:44 +0300 Subject: [PATCH 46/59] hwmon: (abituguru3) Add AUX4 fan input for Abit IP35 Pro Abit IP35 Pro has 6 fan connectors (CPU, SYS and AUX1-4), but the entry for AUX4 was missing from the table. Signed-off-by: Sergey Vlasov Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/abituguru3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index d9f04ce90327..ed33fddc4dee 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -528,6 +528,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX1 Fan", 33, 2, 60, 1, 0 }, { "AUX2 Fan", 35, 2, 60, 1, 0 }, { "AUX3 Fan", 36, 2, 60, 1, 0 }, + { "AUX4 Fan", 37, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, { 0x001B, "unknown", { From ff8421f733c91a70d8edadf9ce2842fca66172fa Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Sun, 27 Jan 2008 16:39:46 -0800 Subject: [PATCH 47/59] hwmon: (dme1737) fix divide-by-0 This patch fixes a possible divide-by-0 and a minor bug in the FAN_FROM_REG macro (in TPC mode). Signed-off-by: Juerg Haefliger Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/dme1737.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 85064fb0b7c2..307f48de051f 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -283,14 +283,21 @@ static inline int TEMP_HYST_TO_REG(int val, int ix, int reg) /* Fan input RPM */ static inline int FAN_FROM_REG(int reg, int tpc) { - return (reg == 0 || reg == 0xffff) ? 0 : - (tpc == 0) ? 90000 * 60 / reg : tpc * reg; + if (tpc) { + return tpc * reg; + } else { + return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg; + } } static inline int FAN_TO_REG(int val, int tpc) { - return SENSORS_LIMIT((tpc == 0) ? 90000 * 60 / val : val / tpc, - 0, 0xffff); + if (tpc) { + return SENSORS_LIMIT(val / tpc, 0, 0xffff); + } else { + return (val <= 0) ? 0xffff : + SENSORS_LIMIT(90000 * 60 / val, 0, 0xfffe); + } } /* Fan TPC (tach pulse count) From 345a22245451c0fd2c44b2afb5dfb75628b487fa Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Sat, 26 Jan 2008 08:54:24 -0800 Subject: [PATCH 48/59] hwmon: (dme1737) fix Super-IO device ID override The dme1737 has a second place where the Super-IO device ID is checked. This has been missed by Jean's initial patch that adds support for user-controlled Super-IO device ID override. This patch fixes this issue. Signed-off-by: Juerg Haefliger Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/dme1737.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 307f48de051f..ddddd9f34c19 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -2030,7 +2030,7 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) /* Check device ID * The DME1737 can return either 0x78 or 0x77 as its device ID. */ - reg = dme1737_sio_inb(sio_cip, 0x20); + reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); if (!(reg == 0x77 || reg == 0x78)) { err = -ENODEV; goto exit; From 8f74efe81d122c071410fd74f42879ef81439fa4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 1 Dec 2007 11:25:33 +0100 Subject: [PATCH 49/59] hwmon: VRM is not written to registers What was true of reading the VRM value is also true of writing it: not being a register value, it doesn't need hardware access, so we don't need a reference to the i2c client. This allows for a minor code cleanup. As gcc appears to be smart enough to simplify the generated code by itself, this cleanup only affects the source code, the generated binaries are unchanged. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1025.c | 3 +-- drivers/hwmon/asb100.c | 6 ++---- drivers/hwmon/lm85.c | 8 ++------ drivers/hwmon/lm87.c | 3 +-- drivers/hwmon/smsc47m192.c | 3 +-- drivers/hwmon/w83791d.c | 6 ++---- drivers/hwmon/w83793.c | 8 ++------ 7 files changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 33cc58b2fadb..e96c3725203d 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -334,8 +334,7 @@ show_vrm(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); + struct adm1025_data *data = dev_get_drvdata(dev); data->vrm = simple_strtoul(buf, NULL, 10); return count; } diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 815493b9788d..3f434de1d993 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -519,10 +519,8 @@ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct asb100_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - data->vrm = val; + struct asb100_data *data = dev_get_drvdata(dev); + data->vrm = simple_strtoul(buf, NULL, 10); return count; } diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 43212db7c798..4bb0f291a6b8 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -443,12 +443,8 @@ static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, c static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - u32 val; - - val = simple_strtoul(buf, NULL, 10); - data->vrm = val; + struct lm85_data *data = dev_get_drvdata(dev); + data->vrm = simple_strtoul(buf, NULL, 10); return count; } diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 7bedf7455e9a..8ee07c5c97a1 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -510,8 +510,7 @@ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char } static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); + struct lm87_data *data = dev_get_drvdata(dev); data->vrm = simple_strtoul(buf, NULL, 10); return count; } diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index b87552652588..8b0c188e60f6 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -341,8 +341,7 @@ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); + struct smsc47m192_data *data = dev_get_drvdata(dev); data->vrm = simple_strtoul(buf, NULL, 10); return count; } diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index a9c01a6f0057..85bd21ee3298 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -840,14 +840,12 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); + struct w83791d_data *data = dev_get_drvdata(dev); /* No lock needed as vrm is internal to the driver (not read from a chip register) and so is not updated in w83791d_update_device() */ - data->vrm = val; + data->vrm = simple_strtoul(buf, NULL, 10); return count; } diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 6b5c99c9e806..3ba1d6b33473 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -243,9 +243,7 @@ static struct i2c_driver w83793_driver = { static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - + struct w83793_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", data->vrm); } @@ -264,9 +262,7 @@ static ssize_t store_vrm(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); - + struct w83793_data *data = dev_get_drvdata(dev); data->vrm = simple_strtoul(buf, NULL, 10); return count; } From af221931519571028c98cf7c7030dd973a524011 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 23:15:49 +0100 Subject: [PATCH 50/59] hwmon: (asb100) Various cleanups * Drop history, it's incomplete and doesn't belong there * Drop unused version number * Drop trailing spaces * Coding style fixes * Fold long lines * Rename new_client to client * Drop redundant initializations to 0 Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/asb100.c | 124 ++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 3f434de1d993..db86bc113905 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -47,12 +47,6 @@ #include #include "lm75.h" -/* - HISTORY: - 2003-12-29 1.0.0 Ported from lm_sensors project for kernel 2.6 -*/ -#define ASB100_VERSION "1.0.0" - /* I2C addresses to scan */ static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; @@ -344,14 +338,14 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long min; unsigned long val = simple_strtoul(buf, NULL, 10); int reg; - + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); data->fan_div[nr] = DIV_TO_REG(val); - switch(nr) { + switch (nr) { case 0: /* fan 1 */ reg = asb100_read_value(client, ASB100_REG_VID_FANDIV); reg = (reg & 0xcf) | (data->fan_div[0] << 4); @@ -429,7 +423,7 @@ static int sprintf_temp_from_reg(u16 reg, char *buf, int nr) } return ret; } - + #define show_temp_reg(reg) \ static ssize_t show_##reg(struct device *dev, char *buf, int nr) \ { \ @@ -502,7 +496,8 @@ sysfs_temp(3); sysfs_temp(4); /* VID */ -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_vid(struct device *dev, struct device_attribute *attr, + char *buf) { struct asb100_data *data = asb100_update_device(dev); return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); @@ -511,13 +506,15 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); /* VRM */ -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, + char *buf) { struct asb100_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", data->vrm); } -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct asb100_data *data = dev_get_drvdata(dev); data->vrm = simple_strtoul(buf, NULL, 10); @@ -527,7 +524,8 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const /* Alarms */ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, + char *buf) { struct asb100_data *data = asb100_update_device(dev); return sprintf(buf, "%u\n", data->alarms); @@ -536,13 +534,15 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); /* 1 PWM */ -static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, + char *buf) { struct asb100_data *data = asb100_update_device(dev); return sprintf(buf, "%d\n", ASB100_PWM_FROM_REG(data->pwm & 0x0f)); } -static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct asb100_data *data = i2c_get_clientdata(client); @@ -556,14 +556,15 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const return count; } -static ssize_t show_pwm_enable1(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_pwm_enable1(struct device *dev, + struct device_attribute *attr, char *buf) { struct asb100_data *data = asb100_update_device(dev); return sprintf(buf, "%d\n", (data->pwm & 0x80) ? 1 : 0); } -static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr, const char *buf, - size_t count) +static ssize_t set_pwm_enable1(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct asb100_data *data = i2c_get_clientdata(client); @@ -653,10 +654,10 @@ static int asb100_attach_adapter(struct i2c_adapter *adapter) } static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, - int kind, struct i2c_client *new_client) + int kind, struct i2c_client *client) { int i, id, err; - struct asb100_data *data = i2c_get_clientdata(new_client); + struct asb100_data *data = i2c_get_clientdata(client); data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (!(data->lm75[0])) { @@ -676,26 +677,26 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, for (i = 2; i <= 3; i++) { if (force_subclients[i] < 0x48 || force_subclients[i] > 0x4f) { - dev_err(&new_client->dev, "invalid subclient " + dev_err(&client->dev, "invalid subclient " "address %d; must be 0x48-0x4f\n", force_subclients[i]); err = -ENODEV; goto ERROR_SC_2; } } - asb100_write_value(new_client, ASB100_REG_I2C_SUBADDR, + asb100_write_value(client, ASB100_REG_I2C_SUBADDR, (force_subclients[2] & 0x07) | - ((force_subclients[3] & 0x07) <<4)); + ((force_subclients[3] & 0x07) << 4)); data->lm75[0]->addr = force_subclients[2]; data->lm75[1]->addr = force_subclients[3]; } else { - int val = asb100_read_value(new_client, ASB100_REG_I2C_SUBADDR); + int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); data->lm75[0]->addr = 0x48 + (val & 0x07); data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07); } - if(data->lm75[0]->addr == data->lm75[1]->addr) { - dev_err(&new_client->dev, "duplicate addresses 0x%x " + if (data->lm75[0]->addr == data->lm75[1]->addr) { + dev_err(&client->dev, "duplicate addresses 0x%x " "for subclients\n", data->lm75[0]->addr); err = -ENODEV; goto ERROR_SC_2; @@ -705,18 +706,17 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, i2c_set_clientdata(data->lm75[i], NULL); data->lm75[i]->adapter = adapter; data->lm75[i]->driver = &asb100_driver; - data->lm75[i]->flags = 0; strlcpy(data->lm75[i]->name, "asb100 subclient", I2C_NAME_SIZE); } if ((err = i2c_attach_client(data->lm75[0]))) { - dev_err(&new_client->dev, "subclient %d registration " + dev_err(&client->dev, "subclient %d registration " "at address 0x%x failed.\n", i, data->lm75[0]->addr); goto ERROR_SC_2; } if ((err = i2c_attach_client(data->lm75[1]))) { - dev_err(&new_client->dev, "subclient %d registration " + dev_err(&client->dev, "subclient %d registration " "at address 0x%x failed.\n", i, data->lm75[1]->addr); goto ERROR_SC_3; } @@ -737,7 +737,7 @@ ERROR_SC_0: static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) { int err; - struct i2c_client *new_client; + struct i2c_client *client; struct asb100_data *data; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { @@ -757,13 +757,12 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) goto ERROR0; } - new_client = &data->client; + client = &data->client; mutex_init(&data->lock); - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &asb100_driver; - new_client->flags = 0; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &asb100_driver; /* Now, we do the remaining detection. */ @@ -773,15 +772,15 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) bank. */ if (kind < 0) { - int val1 = asb100_read_value(new_client, ASB100_REG_BANK); - int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN); + int val1 = asb100_read_value(client, ASB100_REG_BANK); + int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); /* If we're in bank 0 */ - if ( (!(val1 & 0x07)) && + if ((!(val1 & 0x07)) && /* Check for ASB100 ID (low byte) */ - ( ((!(val1 & 0x80)) && (val2 != 0x94)) || + (((!(val1 & 0x80)) && (val2 != 0x94)) || /* Check for ASB100 ID (high byte ) */ - ((val1 & 0x80) && (val2 != 0x06)) ) ) { + ((val1 & 0x80) && (val2 != 0x06)))) { pr_debug("asb100.o: detect failed, " "bad chip id 0x%02x!\n", val2); err = -ENODEV; @@ -792,19 +791,19 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) /* We have either had a force parameter, or we have already detected Winbond. Put it now into bank 0 and Vendor ID High Byte */ - asb100_write_value(new_client, ASB100_REG_BANK, - (asb100_read_value(new_client, ASB100_REG_BANK) & 0x78) | 0x80); + asb100_write_value(client, ASB100_REG_BANK, + (asb100_read_value(client, ASB100_REG_BANK) & 0x78) | 0x80); /* Determine the chip type. */ if (kind <= 0) { - int val1 = asb100_read_value(new_client, ASB100_REG_WCHIPID); - int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN); + int val1 = asb100_read_value(client, ASB100_REG_WCHIPID); + int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); if ((val1 == 0x31) && (val2 == 0x06)) kind = asb100; else { if (kind == 0) - dev_warn(&new_client->dev, "ignoring " + dev_warn(&client->dev, "ignoring " "'force' parameter for unknown chip " "at adapter %d, address 0x%02x.\n", i2c_adapter_id(adapter), address); @@ -814,34 +813,32 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) } /* Fill in remaining client fields and put it into the global list */ - strlcpy(new_client->name, "asb100", I2C_NAME_SIZE); + strlcpy(client->name, "asb100", I2C_NAME_SIZE); data->type = kind; - - data->valid = 0; mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto ERROR1; /* Attach secondary lm75 clients */ if ((err = asb100_detect_subclients(adapter, address, kind, - new_client))) + client))) goto ERROR2; /* Initialize the chip */ - asb100_init_client(new_client); + asb100_init_client(client); /* A few vars need to be filled upon startup */ - data->fan_min[0] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(0)); - data->fan_min[1] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(1)); - data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2)); + data->fan_min[0] = asb100_read_value(client, ASB100_REG_FAN_MIN(0)); + data->fan_min[1] = asb100_read_value(client, ASB100_REG_FAN_MIN(1)); + data->fan_min[2] = asb100_read_value(client, ASB100_REG_FAN_MIN(2)); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &asb100_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &asb100_group))) goto ERROR3; - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto ERROR4; @@ -850,14 +847,14 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) return 0; ERROR4: - sysfs_remove_group(&new_client->dev.kobj, &asb100_group); + sysfs_remove_group(&client->dev.kobj, &asb100_group); ERROR3: i2c_detach_client(data->lm75[1]); i2c_detach_client(data->lm75[0]); kfree(data->lm75[1]); kfree(data->lm75[0]); ERROR2: - i2c_detach_client(new_client); + i2c_detach_client(client); ERROR1: kfree(data); ERROR0: @@ -913,17 +910,17 @@ static int asb100_read_value(struct i2c_client *client, u16 reg) /* convert from ISA to LM75 I2C addresses */ switch (reg & 0xff) { case 0x50: /* TEMP */ - res = swab16(i2c_smbus_read_word_data (cl, 0)); + res = swab16(i2c_smbus_read_word_data(cl, 0)); break; case 0x52: /* CONFIG */ res = i2c_smbus_read_byte_data(cl, 1); break; case 0x53: /* HYST */ - res = swab16(i2c_smbus_read_word_data (cl, 2)); + res = swab16(i2c_smbus_read_word_data(cl, 2)); break; case 0x55: /* MAX */ default: - res = swab16(i2c_smbus_read_word_data (cl, 3)); + res = swab16(i2c_smbus_read_word_data(cl, 3)); break; } } @@ -986,7 +983,7 @@ static void asb100_init_client(struct i2c_client *client) vid = vid_from_reg(vid, data->vrm); /* Start monitoring */ - asb100_write_value(client, ASB100_REG_CONFIG, + asb100_write_value(client, ASB100_REG_CONFIG, (asb100_read_value(client, ASB100_REG_CONFIG) & 0xf7) | 0x01); } @@ -1075,4 +1072,3 @@ MODULE_LICENSE("GPL"); module_init(asb100_init); module_exit(asb100_exit); - From fad33c5fdae73a75af2f8ecf69147011bd57e28c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 23:21:07 +0100 Subject: [PATCH 51/59] hwmon: (asb100) De-macro the sysfs callbacks Use standard dynamic sysfs callbacks instead of macro-generated wrappers. This makes the code more readable, and the binary smaller (by about 12%). Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/asb100.c | 229 ++++++++++++++++------------------------- 1 file changed, 88 insertions(+), 141 deletions(-) diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index db86bc113905..407c86c20ecb 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -221,8 +222,10 @@ static struct i2c_driver asb100_driver = { /* 7 Voltages */ #define show_in_reg(reg) \ -static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ + int nr = to_sensor_dev_attr(attr)->index; \ struct asb100_data *data = asb100_update_device(dev); \ return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \ } @@ -232,9 +235,10 @@ show_in_reg(in_min) show_in_reg(in_max) #define set_in_reg(REG, reg) \ -static ssize_t set_in_##reg(struct device *dev, const char *buf, \ - size_t count, int nr) \ +static ssize_t set_in_##reg(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ { \ + int nr = to_sensor_dev_attr(attr)->index; \ struct i2c_client *client = to_i2c_client(dev); \ struct asb100_data *data = i2c_get_clientdata(client); \ unsigned long val = simple_strtoul(buf, NULL, 10); \ @@ -251,37 +255,12 @@ set_in_reg(MIN, min) set_in_reg(MAX, max) #define sysfs_in(offset) \ -static ssize_t \ - show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in(dev, buf, offset); \ -} \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in##offset, NULL); \ -static ssize_t \ - show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_min(dev, buf, offset); \ -} \ -static ssize_t \ - show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_max(dev, buf, offset); \ -} \ -static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_min(dev, buf, count, offset); \ -} \ -static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_max(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in##offset##_min, set_in##offset##_min); \ -static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in##offset##_max, set_in##offset##_max); +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset) sysfs_in(0); sysfs_in(1); @@ -292,29 +271,36 @@ sysfs_in(5); sysfs_in(6); /* 3 Fans */ -static ssize_t show_fan(struct device *dev, char *buf, int nr) +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct asb100_data *data = asb100_update_device(dev); return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); } -static ssize_t show_fan_min(struct device *dev, char *buf, int nr) +static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct asb100_data *data = asb100_update_device(dev); return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]))); } -static ssize_t show_fan_div(struct device *dev, char *buf, int nr) +static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct asb100_data *data = asb100_update_device(dev); return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); } -static ssize_t set_fan_min(struct device *dev, const char *buf, - size_t count, int nr) +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct asb100_data *data = i2c_get_clientdata(client); u32 val = simple_strtoul(buf, NULL, 10); @@ -330,9 +316,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, determined in part by the fan divisor. This follows the principle of least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ -static ssize_t set_fan_div(struct device *dev, const char *buf, - size_t count, int nr) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct asb100_data *data = i2c_get_clientdata(client); unsigned long min; @@ -375,34 +362,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, } #define sysfs_fan(offset) \ -static ssize_t show_fan##offset(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_min(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_div(dev, buf, offset - 1); \ -} \ -static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - return set_fan_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_fan##offset##_div(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - return set_fan_div(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan##offset, NULL); \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan##offset##_min, set_fan##offset##_min); \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan##offset##_div, set_fan##offset##_div); +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_min, set_fan_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ + show_fan_div, set_fan_div, offset - 1) sysfs_fan(1); sysfs_fan(2); @@ -425,8 +390,10 @@ static int sprintf_temp_from_reg(u16 reg, char *buf, int nr) } #define show_temp_reg(reg) \ -static ssize_t show_##reg(struct device *dev, char *buf, int nr) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ + int nr = to_sensor_dev_attr(attr)->index; \ struct asb100_data *data = asb100_update_device(dev); \ return sprintf_temp_from_reg(data->reg[nr], buf, nr); \ } @@ -436,9 +403,10 @@ show_temp_reg(temp_max); show_temp_reg(temp_hyst); #define set_temp_reg(REG, reg) \ -static ssize_t set_##reg(struct device *dev, const char *buf, \ - size_t count, int nr) \ +static ssize_t set_##reg(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ { \ + int nr = to_sensor_dev_attr(attr)->index; \ struct i2c_client *client = to_i2c_client(dev); \ struct asb100_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ @@ -462,33 +430,12 @@ set_temp_reg(MAX, temp_max); set_temp_reg(HYST, temp_hyst); #define sysfs_temp(num) \ -static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp(dev, buf, num-1); \ -} \ -static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL); \ -static ssize_t show_temp_max##num(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_max(dev, buf, num-1); \ -} \ -static ssize_t set_temp_max##num(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - return set_temp_max(dev, buf, count, num-1); \ -} \ -static DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \ - show_temp_max##num, set_temp_max##num); \ -static ssize_t show_temp_hyst##num(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_hyst(dev, buf, num-1); \ -} \ -static ssize_t set_temp_hyst##num(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - return set_temp_hyst(dev, buf, count, num-1); \ -} \ -static DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_hyst##num, set_temp_hyst##num); +static SENSOR_DEVICE_ATTR(temp##num##_input, S_IRUGO, \ + show_temp, NULL, num - 1); \ +static SENSOR_DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, num - 1); \ +static SENSOR_DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \ + show_temp_hyst, set_temp_hyst, num - 1) sysfs_temp(1); sysfs_temp(2); @@ -583,50 +530,50 @@ static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable1, set_pwm_enable1); static struct attribute *asb100_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_input.attr, - &dev_attr_in1_min.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_input.attr, - &dev_attr_in2_min.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_input.attr, - &dev_attr_in3_min.attr, - &dev_attr_in3_max.attr, - &dev_attr_in4_input.attr, - &dev_attr_in4_min.attr, - &dev_attr_in4_max.attr, - &dev_attr_in5_input.attr, - &dev_attr_in5_min.attr, - &dev_attr_in5_max.attr, - &dev_attr_in6_input.attr, - &dev_attr_in6_min.attr, - &dev_attr_in6_max.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in6_min.dev_attr.attr, + &sensor_dev_attr_in6_max.dev_attr.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan2_div.attr, - &dev_attr_fan3_input.attr, - &dev_attr_fan3_min.attr, - &dev_attr_fan3_div.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan3_div.dev_attr.attr, - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp2_max_hyst.attr, - &dev_attr_temp3_input.attr, - &dev_attr_temp3_max.attr, - &dev_attr_temp3_max_hyst.attr, - &dev_attr_temp4_input.attr, - &dev_attr_temp4_max.attr, - &dev_attr_temp4_max_hyst.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, From 636866b9f0a72583d2361a897668eb19ff37ded6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 23:24:24 +0100 Subject: [PATCH 52/59] hwmon: (asb100) Add individual alarm files The new libsensors needs these individual alarm files. I did not create alarm files for in5 and in6 as these alarms are documented as not working. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/asb100.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 407c86c20ecb..950cea8d1d65 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -480,6 +480,25 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct asb100_data *data = asb100_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); + /* 1 PWM */ static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf) @@ -575,6 +594,18 @@ static struct attribute *asb100_attributes[] = { &sensor_dev_attr_temp4_max.dev_attr.attr, &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, &dev_attr_alarms.attr, From cbe311f2a40b8430d8e01b97c11e9e95d888430b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 21:22:44 +0100 Subject: [PATCH 53/59] hwmon: (w83627ehf) The W83627DHG has 8 VID pins While the W83627EHF/EHG has only 6 VID pins, the W83627DHG has 8 VID pins, to support VRD 11.0. Add support for this. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- Documentation/hwmon/w83627ehf | 5 +++-- drivers/hwmon/w83627ehf.c | 18 ++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf index ccc2bcb61068..d6e1ae30fa6e 100644 --- a/Documentation/hwmon/w83627ehf +++ b/Documentation/hwmon/w83627ehf @@ -23,8 +23,9 @@ W83627DHG super I/O chips. We will refer to them collectively as Winbond chips. The chips implement three temperature sensors, five fan rotation speed sensors, ten analog voltage sensors (only nine for the 627DHG), one -VID (6 pins), alarms with beep warnings (control unimplemented), and -some automatic fan regulation strategies (plus manual fan control mode). +VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG), alarms with beep +warnings (control unimplemented), and some automatic fan regulation +strategies (plus manual fan control mode). Temperatures are measured in degrees Celsius and measurement resolution is 1 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 699592855bd8..075164dd65a7 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -1202,8 +1202,7 @@ static void w83627ehf_device_remove_files(struct device *dev) device_remove_file(dev, &sda_temp[i].dev_attr); device_remove_file(dev, &dev_attr_name); - if (data->vid != 0x3f) - device_remove_file(dev, &dev_attr_cpu0_vid); + device_remove_file(dev, &dev_attr_cpu0_vid); } /* Get the monitoring functions started */ @@ -1303,11 +1302,16 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) } } - data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f; + data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA); + if (sio_data->kind == w83627ehf) /* 6 VID pins only */ + data->vid &= 0x3f; + + err = device_create_file(dev, &dev_attr_cpu0_vid); + if (err) + goto exit_release; } else { dev_info(dev, "VID pins in output mode, CPU VID not " "available\n"); - data->vid = 0x3f; } /* fan4 and fan5 share some pins with the GPIO and serial flash */ @@ -1390,12 +1394,6 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) if (err) goto exit_remove; - if (data->vid != 0x3f) { - err = device_create_file(dev, &dev_attr_cpu0_vid); - if (err) - goto exit_remove; - } - data->hwmon_dev = hwmon_device_register(dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); From ef878b11ba245d14b7db7816217a825d6a894182 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 22:54:13 +0100 Subject: [PATCH 54/59] hwmon: (w83627hf) Enable VBAT monitoring If VBAT monitoring is disabled, enable it. Bug reported on the lm-sensors trac system: http://lm-sensors.org/ticket/2282 This is the exact same patch that was applied to the w83627ehf driver 6 months ago. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83627hf.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 181f4e8590b1..185ae1b8027d 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -1515,6 +1515,11 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev) (w83627hf_read_value(data, W83781D_REG_CONFIG) & 0xf7) | 0x01); + + /* Enable VBAT monitoring if needed */ + tmp = w83627hf_read_value(data, W83781D_REG_VBAT); + if (!(tmp & 0x01)) + w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01); } static void w83627hf_update_fan_div(struct w83627hf_data *data) From e3604c626cdcddf37bf5c9663ae75b79dad40000 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 23:00:30 +0100 Subject: [PATCH 55/59] hwmon: (w83627hf) Add individual alarm and beep files The new libsensors needs these individual alarm and beep files. The code was copied from the w83781d driver. I've tested the alarm files on a W83627THF. I couldn't test the beep files as the system in question doesn't have a speaker. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83627hf.c | 142 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 185ae1b8027d..c02c3bbde19f 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -717,6 +717,29 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); +static ssize_t +show_alarm(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16); +static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); + #define show_beep_reg(REG, reg) \ static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ { \ @@ -777,6 +800,91 @@ static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \ sysfs_beep(ENABLE, enable); sysfs_beep(MASK, mask); +static ssize_t +show_beep(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); +} + +static ssize_t +store_beep(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct w83627hf_data *data = dev_get_drvdata(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + unsigned long bit; + u8 reg; + + bit = simple_strtoul(buf, NULL, 10); + if (bit & ~1) + return -EINVAL; + + mutex_lock(&data->update_lock); + if (bit) + data->beep_mask |= (1 << bitnr); + else + data->beep_mask &= ~(1 << bitnr); + + if (bitnr < 8) { + reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1); + if (bit) + reg |= (1 << bitnr); + else + reg &= ~(1 << bitnr); + w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg); + } else if (bitnr < 16) { + reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); + if (bit) + reg |= (1 << (bitnr - 8)); + else + reg &= ~(1 << (bitnr - 8)); + w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg); + } else { + reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3); + if (bit) + reg |= (1 << (bitnr - 16)); + else + reg &= ~(1 << (bitnr - 16)); + w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg); + } + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 0); +static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 1); +static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 2); +static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 3); +static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 8); +static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 9); +static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 10); +static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 16); +static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 17); +static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 6); +static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 7); +static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 11); +static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 4); +static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 5); +static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 13); + static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -1077,23 +1185,31 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, #define VIN_UNIT_ATTRS(_X_) \ &sensor_dev_attr_in##_X_##_input.dev_attr.attr, \ &sensor_dev_attr_in##_X_##_min.dev_attr.attr, \ - &sensor_dev_attr_in##_X_##_max.dev_attr.attr + &sensor_dev_attr_in##_X_##_max.dev_attr.attr, \ + &sensor_dev_attr_in##_X_##_alarm.dev_attr.attr, \ + &sensor_dev_attr_in##_X_##_beep.dev_attr.attr #define FAN_UNIT_ATTRS(_X_) \ &sensor_dev_attr_fan##_X_##_input.dev_attr.attr, \ &sensor_dev_attr_fan##_X_##_min.dev_attr.attr, \ - &sensor_dev_attr_fan##_X_##_div.dev_attr.attr + &sensor_dev_attr_fan##_X_##_div.dev_attr.attr, \ + &sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr, \ + &sensor_dev_attr_fan##_X_##_beep.dev_attr.attr #define TEMP_UNIT_ATTRS(_X_) \ &sensor_dev_attr_temp##_X_##_input.dev_attr.attr, \ &sensor_dev_attr_temp##_X_##_max.dev_attr.attr, \ &sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr, \ - &sensor_dev_attr_temp##_X_##_type.dev_attr.attr + &sensor_dev_attr_temp##_X_##_type.dev_attr.attr, \ + &sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr, \ + &sensor_dev_attr_temp##_X_##_beep.dev_attr.attr static struct attribute *w83627hf_attributes[] = { &dev_attr_in0_input.attr, &dev_attr_in0_min.attr, &dev_attr_in0_max.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in0_beep.dev_attr.attr, VIN_UNIT_ATTRS(2), VIN_UNIT_ATTRS(3), VIN_UNIT_ATTRS(4), @@ -1196,12 +1312,20 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) &sensor_dev_attr_in5_min.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in5_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in5_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in5_beep.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in6_input.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in6_min.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in6_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in6_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in6_beep.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_pwm1_freq.dev_attr)) || (err = device_create_file(dev, @@ -1215,18 +1339,30 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) &sensor_dev_attr_in1_min.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in1_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in1_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in1_beep.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_fan3_input.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_fan3_min.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_fan3_div.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan3_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan3_beep.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_temp3_input.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_temp3_max.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_temp3_max_hyst.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_beep.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_temp3_type.dev_attr))) goto ERROR4; From 1c1381076f8c6cf0a2c9918194e3fa6369cdf06a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Jan 2008 23:04:55 +0100 Subject: [PATCH 56/59] hwmon: (w83627hf) Refactor beep enable handling We can handle the beep enable bit as any other beep mask bit for slightly smaller code. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83627hf.c | 76 +++++++++++++--------------------------- 1 file changed, 25 insertions(+), 51 deletions(-) diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index c02c3bbde19f..9564fb069957 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -323,10 +323,8 @@ static inline u8 pwm_freq_to_reg(unsigned long val) return (0x80 | (180000UL / (val << 8))); } -#define BEEP_MASK_FROM_REG(val) (val) -#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) -#define BEEP_ENABLE_TO_REG(val) ((val)?1:0) -#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0) +#define BEEP_MASK_FROM_REG(val) ((val) & 0xff7fff) +#define BEEP_MASK_TO_REG(val) ((val) & 0xff7fff) #define DIV_FROM_REG(val) (1 << (val)) @@ -367,7 +365,6 @@ struct w83627hf_data { u8 vid; /* Register encoding, combined */ u32 alarms; /* Register encoding, combined */ u32 beep_mask; /* Register encoding, combined */ - u8 beep_enable; /* Boolean */ u8 pwm[3]; /* Register value */ u8 pwm_freq[3]; /* Register value */ u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode; @@ -740,65 +737,41 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); -#define show_beep_reg(REG, reg) \ -static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct w83627hf_data *data = w83627hf_update_device(dev); \ - return sprintf(buf,"%ld\n", \ - (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \ +static ssize_t +show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + return sprintf(buf, "%ld\n", + (long)BEEP_MASK_FROM_REG(data->beep_mask)); } -show_beep_reg(ENABLE, enable) -show_beep_reg(MASK, mask) - -#define BEEP_ENABLE 0 /* Store beep_enable */ -#define BEEP_MASK 1 /* Store beep_mask */ static ssize_t -store_beep_reg(struct device *dev, const char *buf, size_t count, - int update_mask) +store_beep_mask(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct w83627hf_data *data = dev_get_drvdata(dev); - u32 val, val2; + unsigned long val; val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); - if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ - data->beep_mask = BEEP_MASK_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, - data->beep_mask & 0xff); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, - ((data->beep_mask) >> 16) & 0xff); - val2 = (data->beep_mask >> 8) & 0x7f; - } else { /* We are storing beep_enable */ - val2 = - w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f; - data->beep_enable = BEEP_ENABLE_TO_REG(val); - } - + /* preserve beep enable */ + data->beep_mask = (data->beep_mask & 0x8000) + | BEEP_MASK_TO_REG(val); + w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, + data->beep_mask & 0xff); + w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, + ((data->beep_mask) >> 16) & 0xff); w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, - val2 | data->beep_enable << 7); + (data->beep_mask >> 8) & 0xff); mutex_unlock(&data->update_lock); return count; } -#define sysfs_beep(REG, reg) \ -static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_beep_##reg(dev, attr, buf); \ -} \ -static ssize_t \ -store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - return store_beep_reg(dev, buf, count, BEEP_##REG); \ -} \ -static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \ - show_regs_beep_##reg, store_regs_beep_##reg); - -sysfs_beep(ENABLE, enable); -sysfs_beep(MASK, mask); +static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, + show_beep_mask, store_beep_mask); static ssize_t show_beep(struct device *dev, struct device_attribute *attr, char *buf) @@ -884,6 +857,8 @@ static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, show_beep, store_beep, 5); static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR, show_beep, store_beep, 13); +static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, + show_beep, store_beep, 15); static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) @@ -1223,7 +1198,7 @@ static struct attribute *w83627hf_attributes[] = { TEMP_UNIT_ATTRS(2), &dev_attr_alarms.attr, - &dev_attr_beep_enable.attr, + &sensor_dev_attr_beep_enable.dev_attr.attr, &dev_attr_beep_mask.attr, &sensor_dev_attr_pwm1.dev_attr.attr, @@ -1748,8 +1723,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) | (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16); i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); - data->beep_enable = i >> 7; - data->beep_mask = ((i & 0x7f) << 8) | + data->beep_mask = (i << 8) | w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) | w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16; data->last_updated = jiffies; From 6cc37ee536bb90c428c8a7cde91f33ffe1fd27bd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 5 Jan 2008 15:35:09 +0100 Subject: [PATCH 57/59] hwmon: (lm80) Various cleanups * Drop trailing whitespace * Fold a long line * Rename new_client to client * Drop redundant initializations to 0 * Drop bogus comment Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm80.c | 49 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 0bde0a382ef1..32dfdf38b161 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -127,7 +127,7 @@ struct lm80_data { u16 alarms; /* Register encoding, combined */ }; -/* +/* * Functions declaration */ @@ -336,7 +336,8 @@ set_temp(hot_hyst, temp_hot_hyst, LM80_REG_TEMP_HOT_HYST); set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX); set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST); -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, + char *buf) { struct lm80_data *data = lm80_update_device(dev); return sprintf(buf, "%u\n", data->alarms); @@ -438,7 +439,7 @@ static const struct attribute_group lm80_group = { static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) { int i, cur; - struct i2c_client *new_client; + struct i2c_client *client; struct lm80_data *data; int err = 0; const char *name; @@ -454,21 +455,20 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &lm80_driver; - new_client->flags = 0; + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &lm80_driver; /* Now, we do the remaining detection. It is lousy. */ - if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0) + if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) goto error_free; for (i = 0x2a; i <= 0x3d; i++) { - cur = i2c_smbus_read_byte_data(new_client, i); - if ((i2c_smbus_read_byte_data(new_client, i + 0x40) != cur) - || (i2c_smbus_read_byte_data(new_client, i + 0x80) != cur) - || (i2c_smbus_read_byte_data(new_client, i + 0xc0) != cur)) + cur = i2c_smbus_read_byte_data(client, i); + if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) + || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) + || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) goto error_free; } @@ -476,27 +476,26 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) kind = lm80; name = "lm80"; - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; + /* Fill in the remaining client fields */ + strlcpy(client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto error_free; /* Initialize the LM80 chip */ - lm80_init_client(new_client); + lm80_init_client(client); /* A few vars need to be filled upon startup */ - data->fan_min[0] = lm80_read_value(new_client, LM80_REG_FAN_MIN(1)); - data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2)); + data->fan_min[0] = lm80_read_value(client, LM80_REG_FAN_MIN(1)); + data->fan_min[1] = lm80_read_value(client, LM80_REG_FAN_MIN(2)); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &lm80_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group))) goto error_detach; - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto error_remove; @@ -505,9 +504,9 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) return 0; error_remove: - sysfs_remove_group(&new_client->dev.kobj, &lm80_group); + sysfs_remove_group(&client->dev.kobj, &lm80_group); error_detach: - i2c_detach_client(new_client); + i2c_detach_client(client); error_free: kfree(data); exit: From f8181762a04a3ff7878d3ec5c013bce9c771d4f7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 5 Jan 2008 15:37:05 +0100 Subject: [PATCH 58/59] hwmon: (lm80) De-macro the sysfs callbacks Use standard dynamic sysfs callbacks instead of macro-generated functions. This makes the code more readable, and the binary smaller (by about 34%). As a side note, another benefit of this type of cleanup is that they shrink the build time. For example, this cleanup saves about 29% of the lm80 driver build time. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm80.c | 245 ++++++++++++++++++++----------------------- 1 file changed, 111 insertions(+), 134 deletions(-) diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 32dfdf38b161..612807c786e2 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -158,105 +159,74 @@ static struct i2c_driver lm80_driver = { #define show_in(suffix, value) \ static ssize_t show_in_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \ { \ + int nr = to_sensor_dev_attr(attr)->index; \ struct lm80_data *data = lm80_update_device(dev); \ - return sprintf(buf, "%d\n", IN_FROM_REG(data->value)); \ + return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \ } -show_in(min0, in_min[0]); -show_in(min1, in_min[1]); -show_in(min2, in_min[2]); -show_in(min3, in_min[3]); -show_in(min4, in_min[4]); -show_in(min5, in_min[5]); -show_in(min6, in_min[6]); -show_in(max0, in_max[0]); -show_in(max1, in_max[1]); -show_in(max2, in_max[2]); -show_in(max3, in_max[3]); -show_in(max4, in_max[4]); -show_in(max5, in_max[5]); -show_in(max6, in_max[6]); -show_in(input0, in[0]); -show_in(input1, in[1]); -show_in(input2, in[2]); -show_in(input3, in[3]); -show_in(input4, in[4]); -show_in(input5, in[5]); -show_in(input6, in[6]); +show_in(min, in_min) +show_in(max, in_max) +show_in(input, in) #define set_in(suffix, value, reg) \ static ssize_t set_in_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ size_t count) \ { \ + int nr = to_sensor_dev_attr(attr)->index; \ struct i2c_client *client = to_i2c_client(dev); \ struct lm80_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ mutex_lock(&data->update_lock);\ - data->value = IN_TO_REG(val); \ - lm80_write_value(client, reg, data->value); \ + data->value[nr] = IN_TO_REG(val); \ + lm80_write_value(client, reg(nr), data->value[nr]); \ mutex_unlock(&data->update_lock);\ return count; \ } -set_in(min0, in_min[0], LM80_REG_IN_MIN(0)); -set_in(min1, in_min[1], LM80_REG_IN_MIN(1)); -set_in(min2, in_min[2], LM80_REG_IN_MIN(2)); -set_in(min3, in_min[3], LM80_REG_IN_MIN(3)); -set_in(min4, in_min[4], LM80_REG_IN_MIN(4)); -set_in(min5, in_min[5], LM80_REG_IN_MIN(5)); -set_in(min6, in_min[6], LM80_REG_IN_MIN(6)); -set_in(max0, in_max[0], LM80_REG_IN_MAX(0)); -set_in(max1, in_max[1], LM80_REG_IN_MAX(1)); -set_in(max2, in_max[2], LM80_REG_IN_MAX(2)); -set_in(max3, in_max[3], LM80_REG_IN_MAX(3)); -set_in(max4, in_max[4], LM80_REG_IN_MAX(4)); -set_in(max5, in_max[5], LM80_REG_IN_MAX(5)); -set_in(max6, in_max[6], LM80_REG_IN_MAX(6)); +set_in(min, in_min, LM80_REG_IN_MIN) +set_in(max, in_max, LM80_REG_IN_MAX) -#define show_fan(suffix, value, div) \ +#define show_fan(suffix, value) \ static ssize_t show_fan_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \ { \ + int nr = to_sensor_dev_attr(attr)->index; \ struct lm80_data *data = lm80_update_device(dev); \ - return sprintf(buf, "%d\n", FAN_FROM_REG(data->value, \ - DIV_FROM_REG(data->div))); \ + return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \ + DIV_FROM_REG(data->fan_div[nr]))); \ } -show_fan(min1, fan_min[0], fan_div[0]); -show_fan(min2, fan_min[1], fan_div[1]); -show_fan(input1, fan[0], fan_div[0]); -show_fan(input2, fan[1], fan_div[1]); +show_fan(min, fan_min) +show_fan(input, fan) -#define show_fan_div(suffix, value) \ -static ssize_t show_fan_div##suffix(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct lm80_data *data = lm80_update_device(dev); \ - return sprintf(buf, "%d\n", DIV_FROM_REG(data->value)); \ +static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct lm80_data *data = lm80_update_device(dev); + return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); } -show_fan_div(1, fan_div[0]); -show_fan_div(2, fan_div[1]); -#define set_fan(suffix, value, reg, div) \ -static ssize_t set_fan_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm80_data *data = i2c_get_clientdata(client); \ - long val = simple_strtoul(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock);\ - data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \ - lm80_write_value(client, reg, data->value); \ - mutex_unlock(&data->update_lock);\ - return count; \ +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct lm80_data *data = i2c_get_clientdata(client); + long val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); + mutex_unlock(&data->update_lock); + return count; } -set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]); -set_fan(min2, fan_min[1], LM80_REG_FAN_MIN(2), fan_div[1]); /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ -static ssize_t set_fan_div(struct device *dev, const char *buf, - size_t count, int nr) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm80_data *data = i2c_get_clientdata(client); unsigned long min, val = simple_strtoul(buf, NULL, 10); @@ -291,15 +261,6 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, return count; } -#define set_fan_div(number) \ -static ssize_t set_fan_div##number(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - return set_fan_div(dev, buf, count, number - 1); \ -} -set_fan_div(1); -set_fan_div(2); - static ssize_t show_temp_input1(struct device *dev, struct device_attribute *attr, char *buf) { struct lm80_data *data = lm80_update_device(dev); @@ -343,35 +304,51 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", data->alarms); } -static DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min0, set_in_min0); -static DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min1, set_in_min1); -static DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min2, set_in_min2); -static DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min3, set_in_min3); -static DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min4, set_in_min4); -static DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min5, set_in_min5); -static DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min6, set_in_min6); -static DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max0, set_in_max0); -static DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max1, set_in_max1); -static DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max2, set_in_max2); -static DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max3, set_in_max3); -static DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max4, set_in_max4); -static DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max5, set_in_max5); -static DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max6, set_in_max6); -static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL); -static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL); -static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL); -static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL); -static DEVICE_ATTR(in4_input, S_IRUGO, show_in_input4, NULL); -static DEVICE_ATTR(in5_input, S_IRUGO, show_in_input5, NULL); -static DEVICE_ATTR(in6_input, S_IRUGO, show_in_input6, NULL); -static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min1, - set_fan_min1); -static DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min2, - set_fan_min2); -static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL); -static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL); -static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div1, set_fan_div1); -static DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div2, set_fan_div2); +static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, + show_in_min, set_in_min, 0); +static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, + show_in_min, set_in_min, 1); +static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, + show_in_min, set_in_min, 2); +static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, + show_in_min, set_in_min, 3); +static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, + show_in_min, set_in_min, 4); +static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, + show_in_min, set_in_min, 5); +static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, + show_in_min, set_in_min, 6); +static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, + show_in_max, set_in_max, 0); +static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, + show_in_max, set_in_max, 1); +static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, + show_in_max, set_in_max, 2); +static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, + show_in_max, set_in_max, 3); +static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, + show_in_max, set_in_max, 4); +static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, + show_in_max, set_in_max, 5); +static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, + show_in_max, set_in_max, 6); +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4); +static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5); +static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6); +static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, + show_fan_min, set_fan_min, 0); +static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, + show_fan_min, set_fan_min, 1); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); +static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, + show_fan_div, set_fan_div, 0); +static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, + show_fan_div, set_fan_div, 1); static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_hot_max, set_temp_hot_max); @@ -395,33 +372,33 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter) } static struct attribute *lm80_attributes[] = { - &dev_attr_in0_min.attr, - &dev_attr_in1_min.attr, - &dev_attr_in2_min.attr, - &dev_attr_in3_min.attr, - &dev_attr_in4_min.attr, - &dev_attr_in5_min.attr, - &dev_attr_in6_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_max.attr, - &dev_attr_in4_max.attr, - &dev_attr_in5_max.attr, - &dev_attr_in6_max.attr, - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - &dev_attr_in2_input.attr, - &dev_attr_in3_input.attr, - &dev_attr_in4_input.attr, - &dev_attr_in5_input.attr, - &dev_attr_in6_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan2_div.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in6_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in6_max.dev_attr.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, &dev_attr_temp1_max_hyst.attr, From e84542f5db655d1ce7b4890832f0e5d19aae965d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 5 Jan 2008 15:40:38 +0100 Subject: [PATCH 59/59] hwmon: (lm80) Add individual alarm files The new libsensors needs these individual alarm files. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm80.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 612807c786e2..a2ca055f3922 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -304,6 +304,14 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", data->alarms); } +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct lm80_data *data = lm80_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} + static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0); static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, @@ -359,6 +367,17 @@ static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_os_max, static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst, set_temp_os_hyst); static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13); /* * Real code @@ -405,7 +424,17 @@ static struct attribute *lm80_attributes[] = { &dev_attr_temp1_crit.attr, &dev_attr_temp1_crit_hyst.attr, &dev_attr_alarms.attr, - + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, NULL };