From b3d5496ea5915fa4848fe307af9f7097f312e932 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 2 Apr 2005 20:31:02 +0200 Subject: [PATCH] I2C: Kill address ranges in non-sensors i2c chip drivers Some months ago, you killed the address ranges mechanism from all sensors i2c chip drivers (both the module parameters and the in-code address lists). I think it was a very good move, as the ranges can easily be replaced by individual addresses, and this allowed for significant cleanups in the i2c core (let alone the impressive size shrink for all these drivers). Unfortunately you did not do the same for non-sensors i2c chip drivers. These need the address ranges even less, so we could get rid of the ranges here as well for another significant i2c core cleanup. Here comes a patch which does just that. Since the process is exactly the same as what you did for the other drivers set already, I did not split this one in parts. A documentation update is included. The change saves 308 bytes in the i2c core, and an average 1382 bytes for chip drivers which use I2C_CLIENT_INSMOD, 126 bytes for those which do not. This change is required if we want to merge the sensors and non-sensors i2c code (and we want to do this). Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Index: gregkh-2.6/Documentation/i2c/writing-clients =================================================================== --- drivers/i2c/chips/isp1301_omap.c | 1 - drivers/i2c/chips/m41t00.c | 3 --- drivers/i2c/chips/rtc8564.c | 3 --- 3 files changed, 7 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 7f29a8aff16..354a2629567 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -145,7 +145,6 @@ static inline void notresponding(struct isp1301 *isp) static unsigned short normal_i2c[] = { ISP_BASE, ISP_BASE + 1, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index e771566dffa..5e463c47bfb 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -40,11 +40,8 @@ static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, - .normal_i2c_range = ignore, .probe = ignore, - .probe_range = ignore, .ignore = ignore, - .ignore_range = ignore, .force = ignore, }; diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c index 5a9deddb626..30f553e7370 100644 --- a/drivers/i2c/chips/rtc8564.c +++ b/drivers/i2c/chips/rtc8564.c @@ -66,11 +66,8 @@ static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, - .normal_i2c_range = ignore, .probe = ignore, - .probe_range = ignore, .ignore = ignore, - .ignore_range = ignore, .force = ignore, }; -- cgit v1.2.3-18-g5258 From 792f156d61d327671f58829dc04ad5609152e393 Mon Sep 17 00:00:00 2001 From: Clemens Koller Date: Mon, 11 Apr 2005 11:49:14 +0200 Subject: [PATCH] I2C: rtc8564.c remove duplicate include [PATCH] I2C rtc8564.c remove duplicate include Trivial fix: removes duplicate include line. Signed-off-by: Clemens Koller Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/rtc8564.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c index 30f553e7370..588fc2261a9 100644 --- a/drivers/i2c/chips/rtc8564.c +++ b/drivers/i2c/chips/rtc8564.c @@ -19,7 +19,6 @@ #include #include /* get the user-level API */ #include -#include #include "rtc8564.h" -- cgit v1.2.3-18-g5258 From 9cb7d18433ea6db04b3999e8d0b8f52fba551c2d Mon Sep 17 00:00:00 2001 From: Sebastian Witt Date: Wed, 13 Apr 2005 22:27:53 +0200 Subject: [PATCH] I2C: add new atxp1 driver Adds support for the Attansic ATXP1 I2C device, found on some x86 plattforms to change CPU and other voltages. Depends on the previous i2c-vid.h patch. Signed-off-by: Sebastian Witt Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/Kconfig | 13 ++ drivers/i2c/chips/Makefile | 1 + drivers/i2c/chips/atxp1.c | 361 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 375 insertions(+) create mode 100644 drivers/i2c/chips/atxp1.c (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 74d23cfce2a..a408c137f28 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -62,6 +62,19 @@ config SENSORS_ASB100 This driver can also be built as a module. If so, the module will be called asb100. +config SENSORS_ATXP1 + tristate "Attansic ATXP1 VID controller" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Attansic ATXP1 VID + controller. + + If your board have such a chip, you are able to control your CPU + core and other voltages. + + This driver can also be built as a module. If so, the module + will be called atxp1. + config SENSORS_DS1621 tristate "Dallas Semiconductor DS1621 and DS1625" depends on I2C && EXPERIMENTAL diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 65599161a17..6fadd78f9cf 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o +obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o obj-$(CONFIG_SENSORS_DS1337) += ds1337.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o diff --git a/drivers/i2c/chips/atxp1.c b/drivers/i2c/chips/atxp1.c new file mode 100644 index 00000000000..570b36c6c2a --- /dev/null +++ b/drivers/i2c/chips/atxp1.c @@ -0,0 +1,361 @@ +/* + atxp1.c - kernel module for setting CPU VID and general purpose + I/Os using the Attansic ATXP1 chip. + + 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 + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); +MODULE_VERSION("0.6.2"); +MODULE_AUTHOR("Sebastian Witt "); + +#define ATXP1_VID 0x00 +#define ATXP1_CVID 0x01 +#define ATXP1_GPIO1 0x06 +#define ATXP1_GPIO2 0x0a +#define ATXP1_VIDENA 0x20 +#define ATXP1_VIDMASK 0x1f +#define ATXP1_GPIO1MASK 0x0f + +static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; +static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; + +SENSORS_INSMOD_1(atxp1); + +static int atxp1_attach_adapter(struct i2c_adapter * adapter); +static int atxp1_detach_client(struct i2c_client * client); +static struct atxp1_data * atxp1_update_device(struct device *dev); +static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind); + +static struct i2c_driver atxp1_driver = { + .owner = THIS_MODULE, + .name = "atxp1", + .flags = I2C_DF_NOTIFY, + .attach_adapter = atxp1_attach_adapter, + .detach_client = atxp1_detach_client, +}; + +struct atxp1_data { + struct i2c_client client; + struct semaphore update_lock; + unsigned long last_updated; + u8 valid; + struct { + u8 vid; /* VID output register */ + u8 cpu_vid; /* VID input from CPU */ + u8 gpio1; /* General purpose I/O register 1 */ + u8 gpio2; /* General purpose I/O register 2 */ + } reg; + u8 vrm; /* Detected CPU VRM */ +}; + +static struct atxp1_data * atxp1_update_device(struct device *dev) +{ + struct i2c_client *client; + struct atxp1_data *data; + + client = to_i2c_client(dev); + data = i2c_get_clientdata(client); + + down(&data->update_lock); + + if ((jiffies - data->last_updated > HZ) || + (jiffies < data->last_updated) || + !data->valid) { + + /* Update local register data */ + data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID); + data->reg.cpu_vid = i2c_smbus_read_byte_data(client, ATXP1_CVID); + data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1); + data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2); + + data->valid = 1; + } + + up(&data->update_lock); + + return(data); +} + +/* sys file functions for cpu0_vid */ +ssize_t atxp1_showvcore(struct device *dev, char *buf) +{ + int size; + struct atxp1_data *data; + + data = atxp1_update_device(dev); + + size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK, data->vrm)); + + return size; +} + +ssize_t atxp1_storevcore(struct device *dev, const char* buf, size_t count) +{ + struct atxp1_data *data; + struct i2c_client *client; + char vid; + char cvid; + unsigned int vcore; + + client = to_i2c_client(dev); + data = atxp1_update_device(dev); + + vcore = simple_strtoul(buf, NULL, 10); + vcore /= 25; + vcore *= 25; + + /* Calculate VID */ + vid = vid_to_reg(vcore, data->vrm); + + if (vid < 0) { + dev_err(dev, "VID calculation failed.\n"); + return -1; + } + + /* If output enabled, use control register value. Otherwise original CPU VID */ + if (data->reg.vid & ATXP1_VIDENA) + cvid = data->reg.vid & ATXP1_VIDMASK; + else + cvid = data->reg.cpu_vid; + + /* Nothing changed, aborting */ + if (vid == cvid) + return count; + + dev_info(dev, "Setting VCore to %d mV (0x%02x)\n", vcore, vid); + + /* Write every 25 mV step to increase stability */ + if (cvid > vid) { + for (; cvid >= vid; cvid--) { + i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA); + } + } + else { + for (; cvid <= vid; cvid++) { + i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA); + } + } + + data->valid = 0; + + return count; +} + +/* CPU core reference voltage + unit: millivolt +*/ +static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, atxp1_storevcore); + +/* sys file functions for GPIO1 */ +ssize_t atxp1_showgpio1(struct device *dev, char *buf) +{ + int size; + struct atxp1_data *data; + + data = atxp1_update_device(dev); + + size = sprintf(buf, "0x%02x\n", data->reg.gpio1 & ATXP1_GPIO1MASK); + + return size; +} + +ssize_t atxp1_storegpio1(struct device *dev, const char* buf, size_t count) +{ + struct atxp1_data *data; + struct i2c_client *client; + unsigned int value; + + client = to_i2c_client(dev); + data = atxp1_update_device(dev); + + value = simple_strtoul(buf, NULL, 16); + + value &= ATXP1_GPIO1MASK; + + if (value != (data->reg.gpio1 & ATXP1_GPIO1MASK)) { + dev_info(dev, "Writing 0x%x to GPIO1.\n", value); + + i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value); + + data->valid = 0; + } + + return count; +} + +/* GPIO1 data register + unit: Four bit as hex (e.g. 0x0f) +*/ +static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1); + +/* sys file functions for GPIO2 */ +ssize_t atxp1_showgpio2(struct device *dev, char *buf) +{ + int size; + struct atxp1_data *data; + + data = atxp1_update_device(dev); + + size = sprintf(buf, "0x%02x\n", data->reg.gpio2); + + return size; +} + +ssize_t atxp1_storegpio2(struct device *dev, const char* buf, size_t count) +{ + struct atxp1_data *data; + struct i2c_client *client; + unsigned int value; + + client = to_i2c_client(dev); + data = atxp1_update_device(dev); + + value = simple_strtoul(buf, NULL, 16) & 0xff; + + if (value != data->reg.gpio2) { + dev_info(dev, "Writing 0x%x to GPIO1.\n", value); + + i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value); + + data->valid = 0; + } + + return count; +} + +/* GPIO2 data register + unit: Eight bit as hex (e.g. 0xff) +*/ +static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2); + + +static int atxp1_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_detect(adapter, &addr_data, &atxp1_detect); +}; + +static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client * new_client; + struct atxp1_data * data; + int err = 0; + u8 temp; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data, 0, sizeof(struct atxp1_data)); + new_client = &data->client; + i2c_set_clientdata(new_client, data); + + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &atxp1_driver; + new_client->flags = 0; + + /* Detect ATXP1, checking if vendor ID registers are all zero */ + if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && + (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) && + (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) && + (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) { + + /* No vendor ID, now checking if registers 0x10,0x11 (non-existent) + * showing the same as register 0x00 */ + temp = i2c_smbus_read_byte_data(new_client, 0x00); + + if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && + (i2c_smbus_read_byte_data(new_client, 0x11) == temp) )) + goto exit_free; + } + + /* Get VRM */ + data->vrm = i2c_which_vrm(); + + if ((data->vrm != 90) && (data->vrm != 91)) { + dev_err(&new_client->dev, "Not supporting VRM %d.%d\n", + data->vrm / 10, data->vrm % 10); + goto exit_free; + } + + strncpy(new_client->name, "atxp1", I2C_NAME_SIZE); + + data->valid = 0; + + init_MUTEX(&data->update_lock); + + err = i2c_attach_client(new_client); + + if (err) + { + dev_err(&new_client->dev, "Attach client error.\n"); + goto exit_free; + } + + device_create_file(&new_client->dev, &dev_attr_gpio1); + device_create_file(&new_client->dev, &dev_attr_gpio2); + device_create_file(&new_client->dev, &dev_attr_cpu0_vid); + + dev_info(&new_client->dev, "Using VRM: %d.%d\n", + data->vrm / 10, data->vrm % 10); + + return 0; + +exit_free: + kfree(data); +exit: + return err; +}; + +static int atxp1_detach_client(struct i2c_client * client) +{ + int err; + + err = i2c_detach_client(client); + + if (err) + dev_err(&client->dev, "Failed to detach client.\n"); + else + kfree(i2c_get_clientdata(client)); + + return err; +}; + +static int __init atxp1_init(void) +{ + return i2c_add_driver(&atxp1_driver); +}; + +static void __exit atxp1_exit(void) +{ + i2c_del_driver(&atxp1_driver); +}; + +module_init(atxp1_init); +module_exit(atxp1_exit); -- cgit v1.2.3-18-g5258 From 69113efac29e5f1b7a03dd4fdca5ede6901f4eb8 Mon Sep 17 00:00:00 2001 From: Greg K-H Date: Tue, 5 Apr 2005 18:00:47 +0200 Subject: [PATCH] I2C: mark all functions static in atxp1 driver Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/atxp1.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/atxp1.c b/drivers/i2c/chips/atxp1.c index 570b36c6c2a..57b0bdde38b 100644 --- a/drivers/i2c/chips/atxp1.c +++ b/drivers/i2c/chips/atxp1.c @@ -99,7 +99,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev) } /* sys file functions for cpu0_vid */ -ssize_t atxp1_showvcore(struct device *dev, char *buf) +static ssize_t atxp1_showvcore(struct device *dev, char *buf) { int size; struct atxp1_data *data; @@ -111,7 +111,7 @@ ssize_t atxp1_showvcore(struct device *dev, char *buf) return size; } -ssize_t atxp1_storevcore(struct device *dev, const char* buf, size_t count) +static ssize_t atxp1_storevcore(struct device *dev, const char* buf, size_t count) { struct atxp1_data *data; struct i2c_client *client; @@ -169,7 +169,7 @@ ssize_t atxp1_storevcore(struct device *dev, const char* buf, size_t count) static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, atxp1_storevcore); /* sys file functions for GPIO1 */ -ssize_t atxp1_showgpio1(struct device *dev, char *buf) +static ssize_t atxp1_showgpio1(struct device *dev, char *buf) { int size; struct atxp1_data *data; @@ -181,7 +181,7 @@ ssize_t atxp1_showgpio1(struct device *dev, char *buf) return size; } -ssize_t atxp1_storegpio1(struct device *dev, const char* buf, size_t count) +static ssize_t atxp1_storegpio1(struct device *dev, const char* buf, size_t count) { struct atxp1_data *data; struct i2c_client *client; @@ -211,7 +211,7 @@ ssize_t atxp1_storegpio1(struct device *dev, const char* buf, size_t count) static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1); /* sys file functions for GPIO2 */ -ssize_t atxp1_showgpio2(struct device *dev, char *buf) +static ssize_t atxp1_showgpio2(struct device *dev, char *buf) { int size; struct atxp1_data *data; @@ -223,7 +223,7 @@ ssize_t atxp1_showgpio2(struct device *dev, char *buf) return size; } -ssize_t atxp1_storegpio2(struct device *dev, const char* buf, size_t count) +static ssize_t atxp1_storegpio2(struct device *dev, const char* buf, size_t count) { struct atxp1_data *data; struct i2c_client *client; -- cgit v1.2.3-18-g5258 From 3e9d0ba1305cd7c6efd2ab3a003e58a27da1796b Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Fri, 8 Apr 2005 15:00:21 +0200 Subject: [PATCH] I2C: ds1337 1/4 Use i2c_transfer to send message, so we get proper bus locking. Signed-off-by: Ladislav Michl Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 07f16c3fb08..e2a6aabdc78 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -3,7 +3,7 @@ * * Copyright (C) 2005 James Chapman * - * based on linux/drivers/acron/char/pcf8583.c + * based on linux/drivers/acorn/char/pcf8583.c * Copyright (C) 2000 Russell King * * This program is free software; you can redistribute it and/or modify @@ -119,8 +119,7 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) msg[1].len = sizeof(buf); msg[1].buf = &buf[0]; - result = client->adapter->algo->master_xfer(client->adapter, - &msg[0], 2); + result = i2c_transfer(client->adapter, msg, 2); dev_dbg(&client->adapter->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n", @@ -194,8 +193,7 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) msg[0].len = sizeof(buf); msg[0].buf = &buf[0]; - result = client->adapter->algo->master_xfer(client->adapter, - &msg[0], 1); + result = i2c_transfer(client->adapter, msg, 1); if (result < 0) { dev_err(&client->adapter->dev, "ds1337[%d]: error " "writing data! %d\n", data->id, result); -- cgit v1.2.3-18-g5258 From 6069ffde15472da9d041a58df490d388bb175d51 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Fri, 8 Apr 2005 15:02:16 +0200 Subject: [PATCH] I2C: ds1337 2/4 Use correct macros to convert between bdc and bin. See linux/bcd.h Signed-off-by: Ladislav Michl Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index e2a6aabdc78..8a9e751d609 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -127,15 +127,15 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) buf[4], buf[5], buf[6]); if (result >= 0) { - dt->tm_sec = BCD_TO_BIN(buf[0]); - dt->tm_min = BCD_TO_BIN(buf[1]); + dt->tm_sec = BCD2BIN(buf[0]); + dt->tm_min = BCD2BIN(buf[1]); val = buf[2] & 0x3f; - dt->tm_hour = BCD_TO_BIN(val); - dt->tm_wday = BCD_TO_BIN(buf[3]) - 1; - dt->tm_mday = BCD_TO_BIN(buf[4]); + dt->tm_hour = BCD2BIN(val); + dt->tm_wday = BCD2BIN(buf[3]) - 1; + dt->tm_mday = BCD2BIN(buf[4]); val = buf[5] & 0x7f; - dt->tm_mon = BCD_TO_BIN(val); - dt->tm_year = 1900 + BCD_TO_BIN(buf[6]); + dt->tm_mon = BCD2BIN(val); + dt->tm_year = 1900 + BCD2BIN(buf[6]); if (buf[5] & 0x80) dt->tm_year += 100; @@ -174,19 +174,19 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday); buf[0] = 0; /* reg offset */ - buf[1] = BIN_TO_BCD(dt->tm_sec); - buf[2] = BIN_TO_BCD(dt->tm_min); - buf[3] = BIN_TO_BCD(dt->tm_hour) | (1 << 6); - buf[4] = BIN_TO_BCD(dt->tm_wday) + 1; - buf[5] = BIN_TO_BCD(dt->tm_mday); - buf[6] = BIN_TO_BCD(dt->tm_mon); + buf[1] = BIN2BCD(dt->tm_sec); + buf[2] = BIN2BCD(dt->tm_min); + buf[3] = BIN2BCD(dt->tm_hour) | (1 << 6); + buf[4] = BIN2BCD(dt->tm_wday) + 1; + buf[5] = BIN2BCD(dt->tm_mday); + buf[6] = BIN2BCD(dt->tm_mon); if (dt->tm_year >= 2000) { val = dt->tm_year - 2000; buf[6] |= (1 << 7); } else { val = dt->tm_year - 1900; } - buf[7] = BIN_TO_BCD(val); + buf[7] = BIN2BCD(val); msg[0].addr = client->addr; msg[0].flags = 0; -- cgit v1.2.3-18-g5258 From d01b79d0613ebb6810bb48baf6e53e9319701fea Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Fri, 8 Apr 2005 15:06:39 +0200 Subject: [PATCH] I2C: ds1337 3/4 dev_{dbg,err} functions should print client's device name. data->id can be dropped from message, because device is determined by bus it hangs on (it has fixed address). Signed-off-by: Ladislav Michl Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 8a9e751d609..89fc02b3c6d 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -95,7 +95,6 @@ static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value) */ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) { - struct ds1337_data *data = i2c_get_clientdata(client); int result; u8 buf[7]; u8 val; @@ -103,9 +102,7 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) u8 offs = 0; if (!dt) { - dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n", - __FUNCTION__); - + dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__); return -EINVAL; } @@ -121,8 +118,7 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) result = i2c_transfer(client->adapter, msg, 2); - dev_dbg(&client->adapter->dev, - "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n", + dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n", __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); @@ -139,14 +135,13 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) if (buf[5] & 0x80) dt->tm_year += 100; - dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, " + dev_dbg(&client->dev, "%s: secs=%d, mins=%d, " "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, dt->tm_sec, dt->tm_min, dt->tm_hour, dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday); } else { - dev_err(&client->adapter->dev, "ds1337[%d]: error reading " - "data! %d\n", data->id, result); + dev_err(&client->dev, "error reading data! %d\n", result); result = -EIO; } @@ -155,20 +150,17 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) { - struct ds1337_data *data = i2c_get_clientdata(client); int result; u8 buf[8]; u8 val; struct i2c_msg msg[1]; if (!dt) { - dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n", - __FUNCTION__); - + dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__); return -EINVAL; } - dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, hours=%d, " + dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, dt->tm_sec, dt->tm_min, dt->tm_hour, dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday); @@ -195,8 +187,7 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) result = i2c_transfer(client->adapter, msg, 1); if (result < 0) { - dev_err(&client->adapter->dev, "ds1337[%d]: error " - "writing data! %d\n", data->id, result); + dev_err(&client->dev, "error writing data! %d\n", result); result = -EIO; } else { result = 0; @@ -208,7 +199,7 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) static int ds1337_command(struct i2c_client *client, unsigned int cmd, void *arg) { - dev_dbg(&client->adapter->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); + dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); switch (cmd) { case DS1337_GET_DATE: -- cgit v1.2.3-18-g5258 From 0b46e334d77b2d3b8b3aa665c81c4afbe9f1f458 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 4 May 2005 08:13:13 +0200 Subject: [PATCH] I2C: ds1337: Make time format consistent with other RTC drivers Make time format consistent with other RTC drivers. Signed-off-by: Ladislav Michl Signed-off-by: James Chapman Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 89fc02b3c6d..0967ec6d794 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -130,8 +130,8 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) dt->tm_wday = BCD2BIN(buf[3]) - 1; dt->tm_mday = BCD2BIN(buf[4]); val = buf[5] & 0x7f; - dt->tm_mon = BCD2BIN(val); - dt->tm_year = 1900 + BCD2BIN(buf[6]); + dt->tm_mon = BCD2BIN(val) - 1; + dt->tm_year = BCD2BIN(buf[6]); if (buf[5] & 0x80) dt->tm_year += 100; @@ -171,12 +171,11 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) buf[3] = BIN2BCD(dt->tm_hour) | (1 << 6); buf[4] = BIN2BCD(dt->tm_wday) + 1; buf[5] = BIN2BCD(dt->tm_mday); - buf[6] = BIN2BCD(dt->tm_mon); - if (dt->tm_year >= 2000) { - val = dt->tm_year - 2000; + buf[6] = BIN2BCD(dt->tm_mon) + 1; + val = dt->tm_year; + if (val >= 100) { + val -= 100; buf[6] |= (1 << 7); - } else { - val = dt->tm_year - 1900; } buf[7] = BIN2BCD(val); -- cgit v1.2.3-18-g5258 From 00588243053bb40d0406c7843833f8fae81294ab Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 4 May 2005 08:13:54 +0200 Subject: [PATCH] I2C: ds1337: i2c_transfer() checking i2c_transfer returns number of sucessfully transfered messages. Change error checking to accordingly. (ds1337_set_datetime never returned sucess) Signed-off-by: Ladislav Michl Signed-off-by: James Chapman Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 0967ec6d794..c4762ac980a 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -122,7 +122,7 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); - if (result >= 0) { + if (result == 2) { dt->tm_sec = BCD2BIN(buf[0]); dt->tm_min = BCD2BIN(buf[1]); val = buf[2] & 0x3f; @@ -140,12 +140,12 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) __FUNCTION__, dt->tm_sec, dt->tm_min, dt->tm_hour, dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday); - } else { - dev_err(&client->dev, "error reading data! %d\n", result); - result = -EIO; + + return 0; } - return result; + dev_err(&client->dev, "error reading data! %d\n", result); + return -EIO; } static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) @@ -185,14 +185,11 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) msg[0].buf = &buf[0]; result = i2c_transfer(client->adapter, msg, 1); - if (result < 0) { - dev_err(&client->dev, "error writing data! %d\n", result); - result = -EIO; - } else { - result = 0; - } + if (result == 1) + return 0; - return result; + dev_err(&client->dev, "error writing data! %d\n", result); + return -EIO; } static int ds1337_command(struct i2c_client *client, unsigned int cmd, -- cgit v1.2.3-18-g5258 From 86919833dbeac668762ae7056ead2d35d070f622 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 4 May 2005 08:14:38 +0200 Subject: [PATCH] I2C: ds1337: search by bus number Chip is searched by bus number rather than its own proprietary id. Signed-off-by: Ladislav Michl Signed-off-by: James Chapman Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index c4762ac980a..8ee818ce013 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -69,13 +69,11 @@ static struct i2c_driver ds1337_driver = { struct ds1337_data { struct i2c_client client; struct list_head list; - int id; }; /* * Internal variables */ -static int ds1337_id; static LIST_HEAD(ds1337_clients); static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value) @@ -213,7 +211,7 @@ static int ds1337_command(struct i2c_client *client, unsigned int cmd, * Public API for access to specific device. Useful for low-level * RTC access from kernel code. */ -int ds1337_do_command(int id, int cmd, void *arg) +int ds1337_do_command(int bus, int cmd, void *arg) { struct list_head *walk; struct list_head *tmp; @@ -221,7 +219,7 @@ int ds1337_do_command(int id, int cmd, void *arg) list_for_each_safe(walk, tmp, &ds1337_clients) { data = list_entry(walk, struct ds1337_data, list); - if (data->id == id) + if (data->client.adapter->nr == bus) return ds1337_command(&data->client, cmd, arg); } @@ -331,7 +329,6 @@ static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind) ds1337_init_client(new_client); /* Add client to local list */ - data->id = ds1337_id++; list_add(&data->list, &ds1337_clients); return 0; -- cgit v1.2.3-18-g5258 From 912b9c0c52b95696165e84d67fdab2af81a2213e Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Tue, 10 May 2005 14:08:04 +0200 Subject: [PATCH] ds1337 driver works also with ds1339 chip On Wed, May 04, 2005 at 12:07:11PM +0200, Jean Delvare wrote: > Additionally, I would welcome an additional patch documenting the fact > that the ds1337 driver will work fine with the Dallas DS1339 real-time > clock chip. Document the fact that ds1337 driver works also with DS1339 real-time clock chip. Signed-off-by: Ladislav Michl Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/Kconfig | 4 ++-- drivers/i2c/chips/ds1337.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index a408c137f28..67be4c988ca 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -379,12 +379,12 @@ menu "Other I2C Chip support" depends on I2C config SENSORS_DS1337 - tristate "Dallas Semiconductor DS1337 Real Time Clock" + tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock" depends on I2C && EXPERIMENTAL select I2C_SENSOR help If you say yes here you get support for Dallas Semiconductor - DS1337 real-time clock chips. + DS1337 and DS1339 real-time clock chips. This driver can also be built as a module. If so, the module will be called ds1337. diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 8ee818ce013..2d12cc80f30 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -10,7 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Driver for Dallas Semiconductor DS1337 real time clock chip + * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip */ #include -- cgit v1.2.3-18-g5258 From da17838c5e7256976c34c5d051dc8fb3c6f364b7 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 11 May 2005 10:32:54 +0200 Subject: [PATCH] ds1337: export ds1337_do_command Signed-off-by: Ladislav Michl Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 2d12cc80f30..36bb38377ba 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -380,5 +380,7 @@ MODULE_AUTHOR("James Chapman "); MODULE_DESCRIPTION("DS1337 RTC driver"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL_GPL(ds1337_do_command); + module_init(ds1337_init); module_exit(ds1337_exit); -- cgit v1.2.3-18-g5258 From f0bb60e7b1a0a26c25d8cbf81dda7afbc8bd2982 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 16 Apr 2005 18:10:02 +0000 Subject: [PATCH] I2C: drivers/i2c/*: #include cleanup Files that don't use CONFIG_* stuff shouldn't include config.h Files that use CONFIG_* stuff should include config.h It's that simple. ;-) Signed-off-by: Alexey Dobriyan Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/adm1021.c | 1 - drivers/i2c/chips/adm1025.c | 1 - drivers/i2c/chips/adm1026.c | 1 - drivers/i2c/chips/ds1337.c | 1 - drivers/i2c/chips/eeprom.c | 1 - drivers/i2c/chips/fscher.c | 1 - drivers/i2c/chips/gl518sm.c | 1 - drivers/i2c/chips/it87.c | 1 - drivers/i2c/chips/lm63.c | 1 - drivers/i2c/chips/lm75.c | 1 - drivers/i2c/chips/lm77.c | 1 - drivers/i2c/chips/lm78.c | 1 - drivers/i2c/chips/lm80.c | 1 - drivers/i2c/chips/lm83.c | 1 - drivers/i2c/chips/lm85.c | 1 - drivers/i2c/chips/lm87.c | 1 - drivers/i2c/chips/lm90.c | 1 - drivers/i2c/chips/max1619.c | 1 - drivers/i2c/chips/pc87360.c | 1 - drivers/i2c/chips/via686a.c | 1 - drivers/i2c/chips/w83781d.c | 1 - drivers/i2c/chips/w83l785ts.c | 1 - 22 files changed, 22 deletions(-) (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c index 9058c395671..f450c0bdc52 100644 --- a/drivers/i2c/chips/adm1021.c +++ b/drivers/i2c/chips/adm1021.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c index 111f0c86c93..1dd823e01ef 100644 --- a/drivers/i2c/chips/adm1025.c +++ b/drivers/i2c/chips/adm1025.c @@ -45,7 +45,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/adm1026.c b/drivers/i2c/chips/adm1026.c index b15fafe8f11..9d2ea21a40c 100644 --- a/drivers/i2c/chips/adm1026.c +++ b/drivers/i2c/chips/adm1026.c @@ -23,7 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 36bb38377ba..74ece8ac1c2 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -13,7 +13,6 @@ * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip */ -#include #include #include #include diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index cbdfa2db6f7..addf0adc24d 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -26,7 +26,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c index c3f37dbec11..da411741c2c 100644 --- a/drivers/i2c/chips/fscher.c +++ b/drivers/i2c/chips/fscher.c @@ -26,7 +26,6 @@ * and Philip Edelbrock */ -#include #include #include #include diff --git a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c index 4316a156225..6bedf729dcf 100644 --- a/drivers/i2c/chips/gl518sm.c +++ b/drivers/i2c/chips/gl518sm.c @@ -36,7 +36,6 @@ * 2004-01-31 Code review and approval. (Jean Delvare) */ -#include #include #include #include diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index 007bdf9e7e2..471eb4295a1 100644 --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -31,7 +31,6 @@ type at module load time. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm63.c b/drivers/i2c/chips/lm63.c index bc68e031392..7bdacfd65d4 100644 --- a/drivers/i2c/chips/lm63.c +++ b/drivers/i2c/chips/lm63.c @@ -37,7 +37,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c index 57c51ac37c0..5be164ed278 100644 --- a/drivers/i2c/chips/lm75.c +++ b/drivers/i2c/chips/lm75.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm77.c b/drivers/i2c/chips/lm77.c index 9d15cd5189f..b98f4495299 100644 --- a/drivers/i2c/chips/lm77.c +++ b/drivers/i2c/chips/lm77.c @@ -25,7 +25,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c index 21b195ff387..24619920a27 100644 --- a/drivers/i2c/chips/lm78.c +++ b/drivers/i2c/chips/lm78.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c index 404057b70e9..8100595feb4 100644 --- a/drivers/i2c/chips/lm80.c +++ b/drivers/i2c/chips/lm80.c @@ -21,7 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c index 4d6d7d21e14..de8f8ea3ffd 100644 --- a/drivers/i2c/chips/lm83.c +++ b/drivers/i2c/chips/lm83.c @@ -27,7 +27,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c index b1976775b4b..d618d103130 100644 --- a/drivers/i2c/chips/lm85.c +++ b/drivers/i2c/chips/lm85.c @@ -23,7 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c index 4372b61a088..1921ed1af18 100644 --- a/drivers/i2c/chips/lm87.c +++ b/drivers/i2c/chips/lm87.c @@ -52,7 +52,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c index 9b127a07f56..d4da90da2ea 100644 --- a/drivers/i2c/chips/lm90.c +++ b/drivers/i2c/chips/lm90.c @@ -70,7 +70,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/i2c/chips/max1619.c b/drivers/i2c/chips/max1619.c index 30a196155fd..bf553dcd97d 100644 --- a/drivers/i2c/chips/max1619.c +++ b/drivers/i2c/chips/max1619.c @@ -26,7 +26,6 @@ */ -#include #include #include #include diff --git a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c index 65637b2cd17..876c68f3af3 100644 --- a/drivers/i2c/chips/pc87360.c +++ b/drivers/i2c/chips/pc87360.c @@ -33,7 +33,6 @@ * the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F). */ -#include #include #include #include diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c index fefc24a9251..65bab3a7090 100644 --- a/drivers/i2c/chips/via686a.c +++ b/drivers/i2c/chips/via686a.c @@ -30,7 +30,6 @@ Warning - only supports a single device. */ -#include #include #include #include diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c index c3926d2d8ac..8912390d301 100644 --- a/drivers/i2c/chips/w83781d.c +++ b/drivers/i2c/chips/w83781d.c @@ -35,7 +35,6 @@ */ -#include #include #include #include diff --git a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c index 74d4b58e423..4469d52aba4 100644 --- a/drivers/i2c/chips/w83l785ts.c +++ b/drivers/i2c/chips/w83l785ts.c @@ -30,7 +30,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include -- cgit v1.2.3-18-g5258 From 40b5cda28aafe3744d8808c21f7959e472a9ecb1 Mon Sep 17 00:00:00 2001 From: Grant Coady Date: Sat, 30 Apr 2005 21:41:29 +1000 Subject: [PATCH] I2C: add new hardware monitor driver: adm9240 Completion of Michiel Rook's port of adm9240 to 2.6 with addition of auto fan clock divider based on Jean Delvare's algorithm, and replaces scaling macros with static inlines. Signed-off-by: Grant Coady Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/Kconfig | 11 + drivers/i2c/chips/Makefile | 1 + drivers/i2c/chips/adm9240.c | 768 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 780 insertions(+) create mode 100644 drivers/i2c/chips/adm9240.c (limited to 'drivers/i2c/chips') diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 67be4c988ca..3c8863f26c7 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -51,6 +51,17 @@ config SENSORS_ADM1031 This driver can also be built as a module. If so, the module will be called adm1031. +config SENSORS_ADM9240 + tristate "Analog Devices ADM9240 and compatibles" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for Analog Devices ADM9240, + Dallas DS1780, National Semiconductor LM81 sensor chips. + + This driver can also be built as a module. If so, the module + will be called adm9240. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on I2C && EXPERIMENTAL diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 6fadd78f9cf..247fc982a6d 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o +obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o obj-$(CONFIG_SENSORS_DS1337) += ds1337.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o diff --git a/drivers/i2c/chips/adm9240.c b/drivers/i2c/chips/adm9240.c new file mode 100644 index 00000000000..0b67eab15d2 --- /dev/null +++ b/drivers/i2c/chips/adm9240.c @@ -0,0 +1,768 @@ +/* + * adm9240.c Part of lm_sensors, Linux kernel modules for hardware + * monitoring + * + * Copyright (C) 1999 Frodo Looijaard + * Philip Edelbrock + * Copyright (C) 2003 Michiel Rook + * Copyright (C) 2005 Grant Coady with valuable + * guidance from Jean Delvare + * + * Driver supports Analog Devices ADM9240 + * Dallas Semiconductor DS1780 + * National Semiconductor LM81 + * + * ADM9240 is the reference, DS1780 and LM81 are register compatibles + * + * Voltage Six inputs are scaled by chip, VID also reported + * Temperature Chip temperature to 0.5'C, maximum and max_hysteris + * Fans 2 fans, low speed alarm, automatic fan clock divider + * Alarms 16-bit map of active alarms + * Analog Out 0..1250 mV output + * + * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear' + * + * Test hardware: Intel SE440BX-2 desktop motherboard --Grant + * + * LM81 extended temp reading not implemented + * + * 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 + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, + I2C_CLIENT_END }; + +static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; + +/* Insmod parameters */ +SENSORS_INSMOD_3(adm9240, ds1780, lm81); + +/* ADM9240 registers */ +#define ADM9240_REG_MAN_ID 0x3e +#define ADM9240_REG_DIE_REV 0x3f +#define ADM9240_REG_CONFIG 0x40 + +#define ADM9240_REG_IN(nr) (0x20 + (nr)) /* 0..5 */ +#define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2) +#define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2) +#define ADM9240_REG_FAN(nr) (0x28 + (nr)) /* 0..1 */ +#define ADM9240_REG_FAN_MIN(nr) (0x3b + (nr)) +#define ADM9240_REG_INT(nr) (0x41 + (nr)) +#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr)) +#define ADM9240_REG_TEMP 0x27 +#define ADM9240_REG_TEMP_HIGH 0x39 +#define ADM9240_REG_TEMP_HYST 0x3a +#define ADM9240_REG_ANALOG_OUT 0x19 +#define ADM9240_REG_CHASSIS_CLEAR 0x46 +#define ADM9240_REG_VID_FAN_DIV 0x47 +#define ADM9240_REG_I2C_ADDR 0x48 +#define ADM9240_REG_VID4 0x49 +#define ADM9240_REG_TEMP_CONF 0x4b + +/* generalised scaling with integer rounding */ +static inline int SCALE(long val, int mul, int div) +{ + if (val < 0) + return (val * mul - div / 2) / div; + else + return (val * mul + div / 2) / div; +} + +/* adm9240 internally scales voltage measurements */ +static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 }; + +static inline unsigned int IN_FROM_REG(u8 reg, int n) +{ + return SCALE(reg, nom_mv[n], 192); +} + +static inline u8 IN_TO_REG(unsigned long val, int n) +{ + return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); +} + +/* temperature range: -40..125, 127 disables temperature alarm */ +static inline s8 TEMP_TO_REG(long val) +{ + return SENSORS_LIMIT(SCALE(val, 1, 1000), -40, 127); +} + +/* two fans, each with low fan speed limit */ +static inline unsigned int FAN_FROM_REG(u8 reg, u8 div) +{ + if (!reg) /* error */ + return -1; + + if (reg == 255) + return 0; + + return SCALE(1350000, 1, reg * div); +} + +/* analog out 0..1250mV */ +static inline u8 AOUT_TO_REG(unsigned long val) +{ + return SENSORS_LIMIT(SCALE(val, 255, 1250), 0, 255); +} + +static inline unsigned int AOUT_FROM_REG(u8 reg) +{ + return SCALE(reg, 1250, 255); +} + +static int adm9240_attach_adapter(struct i2c_adapter *adapter); +static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind); +static void adm9240_init_client(struct i2c_client *client); +static int adm9240_detach_client(struct i2c_client *client); +static struct adm9240_data *adm9240_update_device(struct device *dev); + +/* driver data */ +static struct i2c_driver adm9240_driver = { + .owner = THIS_MODULE, + .name = "adm9240", + .id = I2C_DRIVERID_ADM9240, + .flags = I2C_DF_NOTIFY, + .attach_adapter = adm9240_attach_adapter, + .detach_client = adm9240_detach_client, +}; + +/* per client data */ +struct adm9240_data { + enum chips type; + struct i2c_client client; + struct semaphore update_lock; + char valid; + unsigned long last_updated_measure; + unsigned long last_updated_config; + + u8 in[6]; /* ro in0_input */ + u8 in_max[6]; /* rw in0_max */ + u8 in_min[6]; /* rw in0_min */ + u8 fan[2]; /* ro fan1_input */ + u8 fan_min[2]; /* rw fan1_min */ + u8 fan_div[2]; /* rw fan1_div, read-only accessor */ + s16 temp; /* ro temp1_input, 9-bit sign-extended */ + s8 temp_high; /* rw temp1_max */ + s8 temp_hyst; /* rw temp1_max_hyst */ + u16 alarms; /* ro alarms */ + u8 aout; /* rw analog_out */ + u8 vid; /* ro vid */ + u8 vrm; /* -- vrm set on startup, no accessor */ +}; + +/* i2c byte read/write interface */ +static int adm9240_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/*** sysfs accessors ***/ + +/* temperature */ +#define show_temp(value, scale) \ +static ssize_t show_##value(struct device *dev, char *buf) \ +{ \ + struct adm9240_data *data = adm9240_update_device(dev); \ + return sprintf(buf, "%d\n", data->value * scale); \ +} +show_temp(temp_high, 1000); +show_temp(temp_hyst, 1000); +show_temp(temp, 500); + +#define set_temp(value, reg) \ +static ssize_t set_##value(struct device *dev, const char *buf, \ + size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct adm9240_data *data = adm9240_update_device(dev); \ + long temp = simple_strtoul(buf, NULL, 10); \ + \ + down(&data->update_lock); \ + data->value = TEMP_TO_REG(temp); \ + adm9240_write_value(client, reg, data->value); \ + up(&data->update_lock); \ + return count; \ +} + +set_temp(temp_high, ADM9240_REG_TEMP_HIGH); +set_temp(temp_hyst, ADM9240_REG_TEMP_HYST); + +static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, + show_temp_high, set_temp_high); +static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, + show_temp_hyst, set_temp_hyst); +static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); + +/* voltage */ +static ssize_t show_in(struct device *dev, char *buf, int nr) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); +} + +static ssize_t show_in_min(struct device *dev, char *buf, int nr) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); +} + +static ssize_t show_in_max(struct device *dev, char *buf, int nr) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); +} + +static ssize_t set_in_min(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val, nr); + adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t set_in_max(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val, nr); + adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]); + up(&data->update_lock); + return count; +} + +#define show_in_offset(offset) \ +static ssize_t show_in##offset(struct device *dev, 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, char *buf) \ +{ \ + return show_in_min(dev, buf, offset); \ +} \ +static ssize_t show_in##offset##_max(struct device *dev, char *buf) \ +{ \ + return show_in_max(dev, buf, offset); \ +} \ +static ssize_t \ +set_in##offset##_min(struct device *dev, const char *buf, size_t count) \ +{ \ + return set_in_min(dev, buf, count, offset); \ +} \ +static ssize_t \ +set_in##offset##_max(struct device *dev, 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); + +show_in_offset(0); +show_in_offset(1); +show_in_offset(2); +show_in_offset(3); +show_in_offset(4); +show_in_offset(5); + +/* fans */ +static ssize_t show_fan(struct device *dev, char *buf, int nr) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], + 1 << data->fan_div[nr])); +} + +static ssize_t show_fan_min(struct device *dev, char *buf, int nr) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], + 1 << data->fan_div[nr])); +} + +static ssize_t show_fan_div(struct device *dev, char *buf, int nr) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", 1 << data->fan_div[nr]); +} + +/* write new fan div, callers must hold data->update_lock */ +static void adm9240_write_fan_div(struct i2c_client *client, int nr, + u8 fan_div) +{ + u8 reg, old, shift = (nr + 2) * 2; + + reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV); + old = (reg >> shift) & 3; + reg &= ~(3 << shift); + reg |= (fan_div << shift); + adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg); + dev_dbg(&client->dev, "fan%d clock divider changed from %u " + "to %u\n", nr + 1, 1 << old, 1 << fan_div); +} + +/* + * set fan speed low limit: + * + * - value is zero: disable fan speed low limit alarm + * + * - value is below fan speed measurement range: enable fan speed low + * limit alarm to be asserted while fan speed too slow to measure + * + * - otherwise: select fan clock divider to suit fan speed low limit, + * measurement code may adjust registers to ensure fan speed reading + */ +static ssize_t set_fan_min(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + u8 new_div; + + down(&data->update_lock); + + if (!val) { + data->fan_min[nr] = 255; + new_div = data->fan_div[nr]; + + dev_dbg(&client->dev, "fan%u low limit set disabled\n", + nr + 1); + + } else if (val < 1350000 / (8 * 254)) { + new_div = 3; + data->fan_min[nr] = 254; + + dev_dbg(&client->dev, "fan%u low limit set minimum %u\n", + nr + 1, FAN_FROM_REG(254, 1 << new_div)); + + } else { + unsigned int new_min = 1350000 / val; + + new_div = 0; + while (new_min > 192 && new_div < 3) { + new_div++; + new_min /= 2; + } + if (!new_min) /* keep > 0 */ + new_min++; + + data->fan_min[nr] = new_min; + + dev_dbg(&client->dev, "fan%u low limit set fan speed %u\n", + nr + 1, FAN_FROM_REG(new_min, 1 << new_div)); + } + + if (new_div != data->fan_div[nr]) { + data->fan_div[nr] = new_div; + adm9240_write_fan_div(client, nr, new_div); + } + adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr), + data->fan_min[nr]); + + up(&data->update_lock); + return count; +} + +#define show_fan_offset(offset) \ +static ssize_t show_fan_##offset (struct device *dev, char *buf) \ +{ \ +return show_fan(dev, buf, offset - 1); \ +} \ +static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \ +{ \ +return show_fan_div(dev, buf, offset - 1); \ +} \ +static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ +{ \ +return show_fan_min(dev, buf, offset - 1); \ +} \ +static ssize_t set_fan_##offset##_min (struct device *dev, \ +const char *buf, size_t count) \ +{ \ +return set_fan_min(dev, buf, count, offset - 1); \ +} \ +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan_##offset, NULL); \ +static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ + show_fan_##offset##_div, NULL); \ +static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_##offset##_min, set_fan_##offset##_min); + +show_fan_offset(1); +show_fan_offset(2); + +/* alarms */ +static ssize_t show_alarms(struct device *dev, char *buf) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%u\n", data->alarms); +} +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + +/* vid */ +static ssize_t show_vid(struct device *dev, char *buf) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); + +/* analog output */ +static ssize_t show_aout(struct device *dev, char *buf) +{ + struct adm9240_data *data = adm9240_update_device(dev); + return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout)); +} + +static ssize_t set_aout(struct device *dev, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->aout = AOUT_TO_REG(val); + adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout); + up(&data->update_lock); + return count; +} +static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); + +/* chassis_clear */ +static ssize_t chassis_clear(struct device *dev, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned long val = simple_strtol(buf, NULL, 10); + + if (val == 1) { + adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80); + dev_dbg(&client->dev, "chassis intrusion latch cleared\n"); + } + return count; +} +static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear); + + +/*** sensor chip detect and driver install ***/ + +static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct adm9240_data *data; + int err = 0; + const char *name = ""; + u8 man_id, die_rev; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct adm9240_data)); + + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &adm9240_driver; + new_client->flags = 0; + + if (kind == 0) { + kind = adm9240; + } + + if (kind < 0) { + + /* verify chip: reg address should match i2c address */ + if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR) + != address) { + dev_err(&adapter->dev, "detect fail: address match, " + "0x%02x\n", address); + goto exit_free; + } + + /* check known chip manufacturer */ + man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID); + + if (man_id == 0x23) { + kind = adm9240; + } else if (man_id == 0xda) { + kind = ds1780; + } else if (man_id == 0x01) { + kind = lm81; + } else { + dev_err(&adapter->dev, "detect fail: unknown manuf, " + "0x%02x\n", man_id); + goto exit_free; + } + + /* successful detect, print chip info */ + die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV); + dev_info(&adapter->dev, "found %s revision %u\n", + man_id == 0x23 ? "ADM9240" : + man_id == 0xda ? "DS1780" : "LM81", die_rev); + } + + /* either forced or detected chip kind */ + if (kind == adm9240) { + name = "adm9240"; + } else if (kind == ds1780) { + name = "ds1780"; + } else if (kind == lm81) { + name = "lm81"; + } + + /* fill in the remaining client fields and attach */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->type = kind; + init_MUTEX(&data->update_lock); + + if ((err = i2c_attach_client(new_client))) + goto exit_free; + + adm9240_init_client(new_client); + + /* populate sysfs filesystem */ + device_create_file(&new_client->dev, &dev_attr_in0_input); + device_create_file(&new_client->dev, &dev_attr_in0_min); + device_create_file(&new_client->dev, &dev_attr_in0_max); + device_create_file(&new_client->dev, &dev_attr_in1_input); + device_create_file(&new_client->dev, &dev_attr_in1_min); + device_create_file(&new_client->dev, &dev_attr_in1_max); + device_create_file(&new_client->dev, &dev_attr_in2_input); + device_create_file(&new_client->dev, &dev_attr_in2_min); + device_create_file(&new_client->dev, &dev_attr_in2_max); + device_create_file(&new_client->dev, &dev_attr_in3_input); + device_create_file(&new_client->dev, &dev_attr_in3_min); + device_create_file(&new_client->dev, &dev_attr_in3_max); + device_create_file(&new_client->dev, &dev_attr_in4_input); + device_create_file(&new_client->dev, &dev_attr_in4_min); + device_create_file(&new_client->dev, &dev_attr_in4_max); + device_create_file(&new_client->dev, &dev_attr_in5_input); + device_create_file(&new_client->dev, &dev_attr_in5_min); + device_create_file(&new_client->dev, &dev_attr_in5_max); + device_create_file(&new_client->dev, &dev_attr_temp1_max); + device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); + device_create_file(&new_client->dev, &dev_attr_temp1_input); + device_create_file(&new_client->dev, &dev_attr_fan1_input); + device_create_file(&new_client->dev, &dev_attr_fan1_div); + device_create_file(&new_client->dev, &dev_attr_fan1_min); + device_create_file(&new_client->dev, &dev_attr_fan2_input); + device_create_file(&new_client->dev, &dev_attr_fan2_div); + device_create_file(&new_client->dev, &dev_attr_fan2_min); + device_create_file(&new_client->dev, &dev_attr_alarms); + device_create_file(&new_client->dev, &dev_attr_aout_output); + device_create_file(&new_client->dev, &dev_attr_chassis_clear); + device_create_file(&new_client->dev, &dev_attr_cpu