Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6: (36 commits)
  [PATCH] hwmon: add required idr locking
  [PATCH] I2C: hwmon: Rename register parameters
  [PATCH] I2C: Drop unneeded i2c-dev.h includes
  [PATCH] I2C: i2c-ixp4xx: Add hwmon class
  [PATCH] I2C: i2c-piix4: Add Broadcom HT-1000 support
  [PATCH] I2C: i2c-amd756-s4882: Improve static mutex initialization
  [PATCH] I2C: i2c-ali1535: Drop redundant mutex
  [PATCH] i2c: Cleanup isp1301_omap
  [PATCH] i2c: Fix i2c-ite name initialization
  [PATCH] i2c: Drop the i2c-frodo bus driver
  [PATCH] i2c: Optimize core_lists mutex usage
  [PATCH] w83781d: Don't reset the chip by default
  [PATCH] w83781d: Document the alarm and beep bits
  [PATCH] w83627ehf: Refactor the sysfs interface
  [PATCH] hwmon: Support the Pentium M VID code
  [PATCH] hwmon: Add support for the Winbond W83687THF
  [PATCH] hwmon: f71805f semaphore to mutex conversions
  [PATCH] hwmon: Semaphore to mutex conversions
  [PATCH] i2c: Semaphore to mutex conversions, part 3
  [PATCH] i2c: Semaphore to mutex conversions, part 2
  ...
This commit is contained in:
Linus Torvalds
2006-03-23 15:51:32 -08:00
81 changed files with 1697 additions and 1777 deletions

View File

@@ -18,6 +18,10 @@ Supported chips:
Prefix: 'w83637hf' Prefix: 'w83637hf'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf
* Winbond W83687THF
Prefix: 'w83687thf'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Provided by Winbond on request
Authors: Authors:
Frodo Looijaard <frodol@dds.nl>, Frodo Looijaard <frodol@dds.nl>,

View File

@@ -36,6 +36,11 @@ Module parameters
Use 'init=0' to bypass initializing the chip. Use 'init=0' to bypass initializing the chip.
Try this if your computer crashes when you load the module. Try this if your computer crashes when you load the module.
* reset int
(default 0)
The driver used to reset the chip on load, but does no more. Use
'reset=1' to restore the old behavior. Report if you need to do this.
force_subclients=bus,caddr,saddr,saddr force_subclients=bus,caddr,saddr,saddr
This is used to force the i2c addresses for subclients of This is used to force the i2c addresses for subclients of
a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b' a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b'
@@ -123,6 +128,25 @@ When an alarm goes off, you can be warned by a beeping signal through
your computer speaker. It is possible to enable all beeping globally, your computer speaker. It is possible to enable all beeping globally,
or only the beeping for some alarms. or only the beeping for some alarms.
Individual alarm and beep bits:
0x000001: in0
0x000002: in1
0x000004: in2
0x000008: in3
0x000010: temp1
0x000020: temp2 (+temp3 on W83781D)
0x000040: fan1
0x000080: fan2
0x000100: in4
0x000200: in5
0x000400: in6
0x000800: fan3
0x001000: chassis
0x002000: temp3 (W83782D and W83627HF only)
0x010000: in7 (W83782D and W83627HF only)
0x020000: in8 (W83782D and W83627HF only)
If an alarm triggers, it will remain triggered until the hardware register 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 is read at least once. This means that the cause for the alarm may
already have disappeared! Note that in the current implementation, all already have disappeared! Note that in the current implementation, all

View File

@@ -4,7 +4,7 @@ Supported adapters:
* Intel 82371AB PIIX4 and PIIX4E * Intel 82371AB PIIX4 and PIIX4E
* Intel 82443MX (440MX) * Intel 82443MX (440MX)
Datasheet: Publicly available at the Intel website Datasheet: Publicly available at the Intel website
* ServerWorks OSB4, CSB5 and CSB6 southbridges * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
Datasheet: Only available via NDA from ServerWorks Datasheet: Only available via NDA from ServerWorks
* Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
Datasheet: Publicly available at the SMSC website http://www.smsc.com Datasheet: Publicly available at the SMSC website http://www.smsc.com

View File

@@ -6,9 +6,10 @@ Module Parameters
----------------- -----------------
* base: int * base: int
Base addresses for the ACCESS.bus controllers Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices
Description Description
----------- -----------
Enable the use of the ACCESS.bus controllers of a SCx200 processor. Enable the use of the ACCESS.bus controller on the Geode SCx200 and
SC1100 processors and the CS5535 and CS5536 Geode companion devices.

View File

@@ -406,13 +406,14 @@ config SENSORS_W83L785TS
will be called w83l785ts. will be called w83l785ts.
config SENSORS_W83627HF config SENSORS_W83627HF
tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF" tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF"
depends on HWMON && I2C && EXPERIMENTAL depends on HWMON && I2C
select I2C_ISA select I2C_ISA
select HWMON_VID select HWMON_VID
help help
If you say yes here you get support for the Winbond W836X7 series If you say yes here you get support for the Winbond W836X7 series
of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and
W83697HF.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called w83627hf. will be called w83627hf.

View File

@@ -26,6 +26,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
@@ -92,7 +93,7 @@ struct adm1021_data {
struct class_device *class_dev; struct class_device *class_dev;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -162,10 +163,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
struct adm1021_data *data = i2c_get_clientdata(client); \ struct adm1021_data *data = i2c_get_clientdata(client); \
int temp = simple_strtoul(buf, NULL, 10); \ int temp = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = TEMP_TO_REG(temp); \ data->value = TEMP_TO_REG(temp); \
adm1021_write_value(client, reg, data->value); \ adm1021_write_value(client, reg, data->value); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
set(temp_max, ADM1021_REG_TOS_W); set(temp_max, ADM1021_REG_TOS_W);
@@ -275,7 +276,7 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
strlcpy(new_client->name, type_name, I2C_NAME_SIZE); strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -351,7 +352,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct adm1021_data *data = i2c_get_clientdata(client); struct adm1021_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -375,7 +376,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -53,6 +53,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* /*
* Addresses to scan * Addresses to scan
@@ -133,7 +134,7 @@ static struct i2c_driver adm1025_driver = {
struct adm1025_data { struct adm1025_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -207,11 +208,11 @@ static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \ data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \
i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \
data->in_min[offset]); \ data->in_min[offset]); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} \ } \
static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
@@ -221,11 +222,11 @@ static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \ data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \
i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \
data->in_max[offset]); \ data->in_max[offset]); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} \ } \
static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
@@ -247,11 +248,11 @@ static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribut
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->temp_min[offset-1] = TEMP_TO_REG(val); \ data->temp_min[offset-1] = TEMP_TO_REG(val); \
i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \
data->temp_min[offset-1]); \ data->temp_min[offset-1]); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} \ } \
static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
@@ -261,11 +262,11 @@ static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribut
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->temp_max[offset-1] = TEMP_TO_REG(val); \ data->temp_max[offset-1] = TEMP_TO_REG(val); \
i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \
data->temp_max[offset-1]); \ data->temp_max[offset-1]); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} \ } \
static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
@@ -404,7 +405,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */ /* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -523,7 +524,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct adm1025_data *data = i2c_get_clientdata(client); struct adm1025_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
int i; int i;
@@ -558,7 +559,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -32,6 +32,7 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
@@ -260,10 +261,10 @@ struct pwm_data {
struct adm1026_data { struct adm1026_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
int valid; /* !=0 if following fields are valid */ int valid; /* !=0 if following fields are valid */
unsigned long last_reading; /* In jiffies */ unsigned long last_reading; /* In jiffies */
unsigned long last_config; /* In jiffies */ unsigned long last_config; /* In jiffies */
@@ -298,9 +299,8 @@ static int adm1026_attach_adapter(struct i2c_adapter *adapter);
static int adm1026_detect(struct i2c_adapter *adapter, int address, static int adm1026_detect(struct i2c_adapter *adapter, int address,
int kind); int kind);
static int adm1026_detach_client(struct i2c_client *client); static int adm1026_detach_client(struct i2c_client *client);
static int adm1026_read_value(struct i2c_client *client, u8 register); static int adm1026_read_value(struct i2c_client *client, u8 reg);
static int adm1026_write_value(struct i2c_client *client, u8 register, static int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
int value);
static void adm1026_print_gpio(struct i2c_client *client); 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 struct adm1026_data *adm1026_update_device(struct device *dev);
@@ -575,7 +575,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
int i; int i;
long value, alarms, gpio; long value, alarms, gpio;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (!data->valid if (!data->valid
|| time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
/* Things that change quickly */ /* Things that change quickly */
@@ -710,7 +710,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n");
data->vid = (data->gpio >> 11) & 0x1f; data->vid = (data->gpio >> 11) & 0x1f;
data->valid = 1; data->valid = 1;
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }
@@ -739,10 +739,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = INS_TO_REG(nr, val); data->in_min[nr] = INS_TO_REG(nr, val);
adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
@@ -762,10 +762,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = INS_TO_REG(nr, val); data->in_max[nr] = INS_TO_REG(nr, val);
adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -813,10 +813,10 @@ static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, c
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
@@ -831,10 +831,10 @@ static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, c
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -874,11 +874,11 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
data->fan_min[nr]); data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -939,7 +939,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
if (new_div == 0) { if (new_div == 0) {
return -EINVAL; return -EINVAL;
} }
down(&data->update_lock); mutex_lock(&data->update_lock);
orig_div = data->fan_div[nr]; orig_div = data->fan_div[nr];
data->fan_div[nr] = DIV_FROM_REG(new_div); data->fan_div[nr] = DIV_FROM_REG(new_div);
@@ -958,7 +958,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
if (data->fan_div[nr] != orig_div) { if (data->fan_div[nr] != orig_div) {
fixup_fan_min(dev,nr,orig_div); fixup_fan_min(dev,nr,orig_div);
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1001,11 +1001,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_min[nr] = TEMP_TO_REG(val); data->temp_min[nr] = TEMP_TO_REG(val);
adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
data->temp_min[nr]); data->temp_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
@@ -1025,11 +1025,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[nr] = TEMP_TO_REG(val); data->temp_max[nr] = TEMP_TO_REG(val);
adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
data->temp_max[nr]); data->temp_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1064,11 +1064,11 @@ static ssize_t set_temp_offset(struct device *dev,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_offset[nr] = TEMP_TO_REG(val); data->temp_offset[nr] = TEMP_TO_REG(val);
adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
data->temp_offset[nr]); data->temp_offset[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1115,11 +1115,11 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_tmin[nr] = TEMP_TO_REG(val); data->temp_tmin[nr] = TEMP_TO_REG(val);
adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
data->temp_tmin[nr]); data->temp_tmin[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1150,11 +1150,11 @@ static ssize_t set_temp_crit_enable(struct device *dev,
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
if ((val == 1) || (val==0)) { if ((val == 1) || (val==0)) {
down(&data->update_lock); mutex_lock(&data->update_lock);
data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); 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); data->config1);
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
return count; return count;
} }
@@ -1184,11 +1184,11 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_crit[nr] = TEMP_TO_REG(val); data->temp_crit[nr] = TEMP_TO_REG(val);
adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
data->temp_crit[nr]); data->temp_crit[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1212,10 +1212,10 @@ static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *a
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->analog_out = DAC_TO_REG(val); data->analog_out = DAC_TO_REG(val);
adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1267,7 +1267,7 @@ static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr,
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
unsigned long mask; unsigned long mask;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->alarm_mask = val & 0x7fffffff; data->alarm_mask = val & 0x7fffffff;
mask = data->alarm_mask mask = data->alarm_mask
| (data->gpio_mask & 0x10000 ? 0x80000000 : 0); | (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
@@ -1282,7 +1282,7 @@ static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr,
mask >>= 8; mask >>= 8;
adm1026_write_value(client, ADM1026_REG_MASK4, adm1026_write_value(client, ADM1026_REG_MASK4,
mask & 0xff); mask & 0xff);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1303,7 +1303,7 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
long gpio; long gpio;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->gpio = val & 0x1ffff; data->gpio = val & 0x1ffff;
gpio = data->gpio; 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);
@@ -1311,7 +1311,7 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const
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); 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);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1331,7 +1331,7 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
long mask; long mask;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->gpio_mask = val & 0x1ffff; data->gpio_mask = val & 0x1ffff;
mask = data->gpio_mask; 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);
@@ -1339,7 +1339,7 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
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); 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);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1359,10 +1359,10 @@ static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, co
if (data->pwm1.enable == 1) { if (data->pwm1.enable == 1) {
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm1.pwm = PWM_TO_REG(val); data->pwm1.pwm = PWM_TO_REG(val);
adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
return count; return count;
} }
@@ -1378,14 +1378,14 @@ static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *att
struct adm1026_data *data = i2c_get_clientdata(client); struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); 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 */ if (data->pwm1.enable == 2) { /* apply immediately */
data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | 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); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1406,7 +1406,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
int old_enable; int old_enable;
if ((val >= 0) && (val < 3)) { if ((val >= 0) && (val < 3)) {
down(&data->update_lock); mutex_lock(&data->update_lock);
old_enable = data->pwm1.enable; old_enable = data->pwm1.enable;
data->pwm1.enable = val; data->pwm1.enable = val;
data->config1 = (data->config1 & ~CFG1_PWM_AFC) data->config1 = (data->config1 & ~CFG1_PWM_AFC)
@@ -1424,7 +1424,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
adm1026_write_value(client, ADM1026_REG_PWM, adm1026_write_value(client, ADM1026_REG_PWM,
data->pwm1.pwm); data->pwm1.pwm);
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
return count; return count;
} }
@@ -1541,7 +1541,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
/* Fill in the remaining client fields */ /* Fill in the remaining client fields */
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))

View File

@@ -28,6 +28,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Following macros takes channel parameter starting from 0 to 2 */ /* Following macros takes channel parameter starting from 0 to 2 */
#define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr))
@@ -70,7 +71,7 @@ typedef u8 auto_chan_table_t[8][2];
struct adm1031_data { struct adm1031_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
int chip_type; int chip_type;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -262,10 +263,10 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr)
old_fan_mode = data->conf1; old_fan_mode = data->conf1;
down(&data->update_lock); mutex_lock(&data->update_lock);
if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) { if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
up(&data->update_lock); mutex_unlock(&data->update_lock);
return ret; return ret;
} }
if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^
@@ -288,7 +289,7 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr)
} }
data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -329,11 +330,11 @@ set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr)
struct adm1031_data *data = i2c_get_clientdata(client); struct adm1031_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
data->auto_temp[nr]); data->auto_temp[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; 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, char *buf, int nr)
@@ -349,11 +350,11 @@ set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr)
struct adm1031_data *data = i2c_get_clientdata(client); struct adm1031_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]); data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
data->temp_max[nr]); data->temp_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -405,11 +406,11 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr)
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
int reg; int reg;
down(&data->update_lock); mutex_lock(&data->update_lock);
if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
(((val>>4) & 0xf) != 5)) { (((val>>4) & 0xf) != 5)) {
/* In automatic mode, the only PWM accepted is 33% */ /* In automatic mode, the only PWM accepted is 33% */
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
data->pwm[nr] = PWM_TO_REG(val); data->pwm[nr] = PWM_TO_REG(val);
@@ -417,7 +418,7 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr)
adm1031_write_value(client, ADM1031_REG_PWM, adm1031_write_value(client, ADM1031_REG_PWM,
nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
: (data->pwm[nr] & 0xf) | (reg & 0xf0)); : (data->pwm[nr] & 0xf) | (reg & 0xf0));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -511,7 +512,7 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr)
struct adm1031_data *data = i2c_get_clientdata(client); struct adm1031_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (val) { if (val) {
data->fan_min[nr] = data->fan_min[nr] =
FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
@@ -519,7 +520,7 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr)
data->fan_min[nr] = 0xff; data->fan_min[nr] = 0xff;
} }
adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t static ssize_t
@@ -540,7 +541,7 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr)
if (tmp == 0xff) if (tmp == 0xff)
return -EINVAL; return -EINVAL;
down(&data->update_lock); mutex_lock(&data->update_lock);
old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]);
new_min = data->fan_min[nr] * old_div / new_min = data->fan_min[nr] * old_div /
@@ -553,7 +554,7 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr)
data->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]); data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -627,11 +628,11 @@ set_temp_min(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtol(buf, NULL, 10); val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_min[nr] = TEMP_TO_REG(val); data->temp_min[nr] = TEMP_TO_REG(val);
adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
data->temp_min[nr]); data->temp_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t static ssize_t
@@ -643,11 +644,11 @@ set_temp_max(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtol(buf, NULL, 10); val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[nr] = TEMP_TO_REG(val); data->temp_max[nr] = TEMP_TO_REG(val);
adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
data->temp_max[nr]); data->temp_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t static ssize_t
@@ -659,11 +660,11 @@ set_temp_crit(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtol(buf, NULL, 10); val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_crit[nr] = TEMP_TO_REG(val); data->temp_crit[nr] = TEMP_TO_REG(val);
adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
data->temp_crit[nr]); data->temp_crit[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -778,7 +779,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -891,7 +892,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
struct adm1031_data *data = i2c_get_clientdata(client); struct adm1031_data *data = i2c_get_clientdata(client);
int chan; int chan;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -965,7 +966,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -49,6 +49,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
@@ -150,7 +151,7 @@ struct adm9240_data {
enum chips type; enum chips type;
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; char valid;
unsigned long last_updated_measure; unsigned long last_updated_measure;
unsigned long last_updated_config; unsigned long last_updated_config;
@@ -195,11 +196,11 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
struct adm9240_data *data = i2c_get_clientdata(client); struct adm9240_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[attr->index] = TEMP_TO_REG(val); data->temp_max[attr->index] = TEMP_TO_REG(val);
i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index), i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index),
data->temp_max[attr->index]); data->temp_max[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -246,11 +247,11 @@ static ssize_t set_in_min(struct device *dev,
struct adm9240_data *data = i2c_get_clientdata(client); struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[attr->index] = IN_TO_REG(val, attr->index); data->in_min[attr->index] = IN_TO_REG(val, attr->index);
i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index), i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index),
data->in_min[attr->index]); data->in_min[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -263,11 +264,11 @@ static ssize_t set_in_max(struct device *dev,
struct adm9240_data *data = i2c_get_clientdata(client); struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[attr->index] = IN_TO_REG(val, attr->index); data->in_max[attr->index] = IN_TO_REG(val, attr->index);
i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index), i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index),
data->in_max[attr->index]); data->in_max[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -350,7 +351,7 @@ static ssize_t set_fan_min(struct device *dev,
int nr = attr->index; int nr = attr->index;
u8 new_div; u8 new_div;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (!val) { if (!val) {
data->fan_min[nr] = 255; data->fan_min[nr] = 255;
@@ -390,7 +391,7 @@ static ssize_t set_fan_min(struct device *dev,
i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr), i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr),
data->fan_min[nr]); data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -439,10 +440,10 @@ static ssize_t set_aout(struct device *dev,
struct adm9240_data *data = i2c_get_clientdata(client); struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtol(buf, NULL, 10); unsigned long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->aout = AOUT_TO_REG(val); data->aout = AOUT_TO_REG(val);
i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout); i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
@@ -539,7 +540,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
/* fill in the remaining client fields and attach */ /* fill in the remaining client fields and attach */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->type = kind; data->type = kind;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
goto exit_free; goto exit_free;
@@ -691,7 +692,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
struct adm9240_data *data = i2c_get_clientdata(client); struct adm9240_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
/* minimum measurement cycle: 1.75 seconds */ /* minimum measurement cycle: 1.75 seconds */
if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
@@ -771,7 +772,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
data->last_updated_config = jiffies; data->last_updated_config = jiffies;
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -44,6 +44,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/mutex.h>
#include "lm75.h" #include "lm75.h"
/* /*
@@ -182,10 +183,10 @@ static u8 DIV_TO_REG(long val)
struct asb100_data { struct asb100_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
/* array of 2 pointers to subclients */ /* array of 2 pointers to subclients */
@@ -245,11 +246,11 @@ static ssize_t set_in_##reg(struct device *dev, const char *buf, \
struct asb100_data *data = i2c_get_clientdata(client); \ struct asb100_data *data = i2c_get_clientdata(client); \
unsigned long val = simple_strtoul(buf, NULL, 10); \ unsigned long val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->in_##reg[nr] = IN_TO_REG(val); \ data->in_##reg[nr] = IN_TO_REG(val); \
asb100_write_value(client, ASB100_REG_IN_##REG(nr), \ asb100_write_value(client, ASB100_REG_IN_##REG(nr), \
data->in_##reg[nr]); \ data->in_##reg[nr]); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
@@ -331,10 +332,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
struct asb100_data *data = i2c_get_clientdata(client); struct asb100_data *data = i2c_get_clientdata(client);
u32 val = simple_strtoul(buf, NULL, 10); u32 val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -351,7 +352,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
int reg; int reg;
down(&data->update_lock); mutex_lock(&data->update_lock);
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])); DIV_FROM_REG(data->fan_div[nr]));
@@ -381,7 +382,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -461,7 +462,7 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \
struct asb100_data *data = i2c_get_clientdata(client); \ struct asb100_data *data = i2c_get_clientdata(client); \
unsigned long val = simple_strtoul(buf, NULL, 10); \ unsigned long val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
switch (nr) { \ switch (nr) { \
case 1: case 2: \ case 1: case 2: \
data->reg[nr] = LM75_TEMP_TO_REG(val); \ data->reg[nr] = LM75_TEMP_TO_REG(val); \
@@ -472,7 +473,7 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \
} \ } \
asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \ asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \
data->reg[nr]); \ data->reg[nr]); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
@@ -574,11 +575,11 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const
struct asb100_data *data = i2c_get_clientdata(client); struct asb100_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm &= 0x80; /* keep the enable bit */ data->pwm &= 0x80; /* keep the enable bit */
data->pwm |= (0x0f & ASB100_PWM_TO_REG(val)); data->pwm |= (0x0f & ASB100_PWM_TO_REG(val));
asb100_write_value(client, ASB100_REG_PWM1, data->pwm); asb100_write_value(client, ASB100_REG_PWM1, data->pwm);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -595,11 +596,11 @@ static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr
struct asb100_data *data = i2c_get_clientdata(client); struct asb100_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm &= 0x0f; /* keep the duty cycle bits */ data->pwm &= 0x0f; /* keep the duty cycle bits */
data->pwm |= (val ? 0x80 : 0x00); data->pwm |= (val ? 0x80 : 0x00);
asb100_write_value(client, ASB100_REG_PWM1, data->pwm); asb100_write_value(client, ASB100_REG_PWM1, data->pwm);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -729,7 +730,7 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
} }
new_client = &data->client; new_client = &data->client;
init_MUTEX(&data->lock); mutex_init(&data->lock);
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
new_client->adapter = adapter; new_client->adapter = adapter;
@@ -789,7 +790,7 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -885,7 +886,7 @@ static int asb100_read_value(struct i2c_client *client, u16 reg)
struct i2c_client *cl; struct i2c_client *cl;
int res, bank; int res, bank;
down(&data->lock); mutex_lock(&data->lock);
bank = (reg >> 8) & 0x0f; bank = (reg >> 8) & 0x0f;
if (bank > 2) if (bank > 2)
@@ -919,7 +920,7 @@ static int asb100_read_value(struct i2c_client *client, u16 reg)
if (bank > 2) if (bank > 2)
i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} }
@@ -930,7 +931,7 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value)
struct i2c_client *cl; struct i2c_client *cl;
int bank; int bank;
down(&data->lock); mutex_lock(&data->lock);
bank = (reg >> 8) & 0x0f; bank = (reg >> 8) & 0x0f;
if (bank > 2) if (bank > 2)
@@ -960,7 +961,7 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value)
if (bank > 2) if (bank > 2)
i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
up(&data->lock); mutex_unlock(&data->lock);
} }
static void asb100_init_client(struct i2c_client *client) static void asb100_init_client(struct i2c_client *client)
@@ -984,7 +985,7 @@ static struct asb100_data *asb100_update_device(struct device *dev)
struct asb100_data *data = i2c_get_clientdata(client); struct asb100_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -1042,7 +1043,7 @@ static struct asb100_data *asb100_update_device(struct device *dev)
dev_dbg(&client->dev, "... device update complete\n"); dev_dbg(&client->dev, "... device update complete\n");
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -26,6 +26,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
@@ -60,7 +61,7 @@ static struct i2c_driver atxp1_driver = {
struct atxp1_data { struct atxp1_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
unsigned long last_updated; unsigned long last_updated;
u8 valid; u8 valid;
struct { struct {
@@ -80,7 +81,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev)
client = to_i2c_client(dev); client = to_i2c_client(dev);
data = i2c_get_clientdata(client); data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
@@ -93,7 +94,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return(data); return(data);
} }
@@ -309,7 +310,7 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
err = i2c_attach_client(new_client); err = i2c_attach_client(new_client);

View File

@@ -28,6 +28,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include "lm75.h" #include "lm75.h"
/* Addresses to scan */ /* Addresses to scan */
@@ -72,7 +73,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
struct ds1621_data { struct ds1621_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -156,10 +157,10 @@ static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *at
struct ds1621_data *data = ds1621_update_client(dev); \ struct ds1621_data *data = ds1621_update_client(dev); \
u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = val; \ data->value = val; \
ds1621_write_value(client, reg, data->value); \ ds1621_write_value(client, reg, data->value); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
@@ -242,7 +243,7 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
/* Fill in remaining client fields and put it into the global list */ /* Fill in remaining client fields and put it into the global list */
strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE); strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -297,7 +298,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
struct ds1621_data *data = i2c_get_clientdata(client); struct ds1621_data *data = i2c_get_clientdata(client);
u8 new_conf; u8 new_conf;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -327,7 +328,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -30,6 +30,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
static struct platform_device *pdev; static struct platform_device *pdev;
@@ -131,10 +132,10 @@ static struct resource f71805f_resource __initdata = {
struct f71805f_data { struct f71805f_data {
unsigned short addr; unsigned short addr;
const char *name; const char *name;
struct semaphore lock; struct mutex lock;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
unsigned long last_limits; /* In jiffies */ unsigned long last_limits; /* In jiffies */
@@ -224,20 +225,20 @@ static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
{ {
u8 val; u8 val;
down(&data->lock); mutex_lock(&data->lock);
outb(reg, data->addr + ADDR_REG_OFFSET); outb(reg, data->addr + ADDR_REG_OFFSET);
val = inb(data->addr + DATA_REG_OFFSET); val = inb(data->addr + DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return val; return val;
} }
static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
{ {
down(&data->lock); mutex_lock(&data->lock);
outb(reg, data->addr + ADDR_REG_OFFSET); outb(reg, data->addr + ADDR_REG_OFFSET);
outb(val, data->addr + DATA_REG_OFFSET); outb(val, data->addr + DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
} }
/* It is important to read the MSB first, because doing so latches the /* It is important to read the MSB first, because doing so latches the
@@ -246,24 +247,24 @@ static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
{ {
u16 val; u16 val;
down(&data->lock); mutex_lock(&data->lock);
outb(reg, data->addr + ADDR_REG_OFFSET); outb(reg, data->addr + ADDR_REG_OFFSET);
val = inb(data->addr + DATA_REG_OFFSET) << 8; val = inb(data->addr + DATA_REG_OFFSET) << 8;
outb(++reg, data->addr + ADDR_REG_OFFSET); outb(++reg, data->addr + ADDR_REG_OFFSET);
val |= inb(data->addr + DATA_REG_OFFSET); val |= inb(data->addr + DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return val; return val;
} }
static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
{ {
down(&data->lock); mutex_lock(&data->lock);
outb(reg, data->addr + ADDR_REG_OFFSET); outb(reg, data->addr + ADDR_REG_OFFSET);
outb(val >> 8, data->addr + DATA_REG_OFFSET); outb(val >> 8, data->addr + DATA_REG_OFFSET);
outb(++reg, data->addr + ADDR_REG_OFFSET); outb(++reg, data->addr + ADDR_REG_OFFSET);
outb(val & 0xff, data->addr + DATA_REG_OFFSET); outb(val & 0xff, data->addr + DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
} }
static struct f71805f_data *f71805f_update_device(struct device *dev) static struct f71805f_data *f71805f_update_device(struct device *dev)
@@ -271,7 +272,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
struct f71805f_data *data = dev_get_drvdata(dev); struct f71805f_data *data = dev_get_drvdata(dev);
int nr; int nr;
down(&data->update_lock); mutex_lock(&data->update_lock);
/* Limit registers cache is refreshed after 60 seconds */ /* Limit registers cache is refreshed after 60 seconds */
if (time_after(jiffies, data->last_updated + 60 * HZ) if (time_after(jiffies, data->last_updated + 60 * HZ)
@@ -323,7 +324,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }
@@ -362,10 +363,10 @@ static ssize_t set_in0_max(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev); struct f71805f_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_high[0] = in0_to_reg(val); data->in_high[0] = in0_to_reg(val);
f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]); f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -376,18 +377,14 @@ static ssize_t set_in0_min(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev); struct f71805f_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_low[0] = in0_to_reg(val); data->in_low[0] = in0_to_reg(val);
f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]); f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
static ssize_t show_in(struct device *dev, struct device_attribute *devattr, static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
char *buf) char *buf)
{ {
@@ -426,10 +423,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute
int nr = attr->index; int nr = attr->index;
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_high[nr] = in_to_reg(val); data->in_high[nr] = in_to_reg(val);
f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -442,31 +439,14 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute
int nr = attr->index; int nr = attr->index;
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_low[nr] = in_to_reg(val); data->in_low[nr] = in_to_reg(val);
f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define sysfs_in(offset) \
static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
show_in, NULL, offset); \
static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
show_in_max, set_in_max, offset); \
static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
show_in_min, set_in_min, offset)
sysfs_in(1);
sysfs_in(2);
sysfs_in(3);
sysfs_in(4);
sysfs_in(5);
sysfs_in(6);
sysfs_in(7);
sysfs_in(8);
static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
char *buf) char *buf)
{ {
@@ -495,24 +475,14 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
int nr = attr->index; int nr = attr->index;
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_low[nr] = fan_to_reg(val); data->fan_low[nr] = fan_to_reg(val);
f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define sysfs_fan(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)
sysfs_fan(1);
sysfs_fan(2);
sysfs_fan(3);
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
char *buf) char *buf)
{ {
@@ -562,10 +532,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute
int nr = attr->index; int nr = attr->index;
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_high[nr] = temp_to_reg(val); data->temp_high[nr] = temp_to_reg(val);
f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -578,28 +548,14 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
int nr = attr->index; int nr = attr->index;
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_hyst[nr] = temp_to_reg(val); data->temp_hyst[nr] = temp_to_reg(val);
f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define sysfs_temp(offset) \
static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
show_temp, NULL, 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##_max_hyst, S_IRUGO | S_IWUSR, \
show_temp_hyst, set_temp_hyst, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \
show_temp_type, NULL, offset - 1)
sysfs_temp(1);
sysfs_temp(2);
sysfs_temp(3);
static ssize_t show_alarms_in(struct device *dev, struct device_attribute static ssize_t show_alarms_in(struct device *dev, struct device_attribute
*devattr, char *buf) *devattr, char *buf)
{ {
@@ -625,10 +581,6 @@ static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
} }
static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
static ssize_t show_name(struct device *dev, struct device_attribute static ssize_t show_name(struct device *dev, struct device_attribute
*devattr, char *buf) *devattr, char *buf)
{ {
@@ -637,7 +589,89 @@ static ssize_t show_name(struct device *dev, struct device_attribute
return sprintf(buf, "%s\n", data->name); return sprintf(buf, "%s\n", data->name);
} }
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static struct device_attribute f71805f_dev_attr[] = {
__ATTR(in0_input, S_IRUGO, show_in0, NULL),
__ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max),
__ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min),
__ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL),
__ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL),
__ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL),
__ATTR(name, S_IRUGO, show_name, NULL),
};
static struct sensor_device_attribute f71805f_sensor_attr[] = {
SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 1),
SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 1),
SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 2),
SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 2),
SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 3),
SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 3),
SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 4),
SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 4),
SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 5),
SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 5),
SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 6),
SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 6),
SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 7),
SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 7),
SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 8),
SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 8),
SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
show_temp_max, set_temp_max, 0),
SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
show_temp_hyst, set_temp_hyst, 0),
SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
show_temp_max, set_temp_max, 1),
SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
show_temp_hyst, set_temp_hyst, 1),
SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
show_temp_max, set_temp_max, 2),
SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
show_temp_hyst, set_temp_hyst, 2),
SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
};
static struct sensor_device_attribute f71805f_fan_attr[] = {
SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 0),
SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 1),
SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 2),
};
/* /*
* Device registration and initialization * Device registration and initialization
@@ -668,7 +702,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
{ {
struct f71805f_data *data; struct f71805f_data *data;
struct resource *res; struct resource *res;
int err; int i, err;
if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
@@ -678,9 +712,9 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
data->addr = res->start; data->addr = res->start;
init_MUTEX(&data->lock); mutex_init(&data->lock);
data->name = "f71805f"; data->name = "f71805f";
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
@@ -695,76 +729,31 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
f71805f_init_device(data); f71805f_init_device(data);
/* Register sysfs interface files */ /* Register sysfs interface files */
device_create_file(&pdev->dev, &dev_attr_in0_input); for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) {
device_create_file(&pdev->dev, &dev_attr_in0_max); err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]);
device_create_file(&pdev->dev, &dev_attr_in0_min); if (err)
device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr); goto exit_class;
device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr);
if (data->fan_enabled & (1 << 0)) {
device_create_file(&pdev->dev,
&sensor_dev_attr_fan1_input.dev_attr);
device_create_file(&pdev->dev,
&sensor_dev_attr_fan1_min.dev_attr);
} }
if (data->fan_enabled & (1 << 1)) { for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) {
device_create_file(&pdev->dev, err = device_create_file(&pdev->dev,
&sensor_dev_attr_fan2_input.dev_attr); &f71805f_sensor_attr[i].dev_attr);
device_create_file(&pdev->dev, if (err)
&sensor_dev_attr_fan2_min.dev_attr); goto exit_class;
} }
if (data->fan_enabled & (1 << 2)) { for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) {
device_create_file(&pdev->dev, if (!(data->fan_enabled & (1 << (i / 2))))
&sensor_dev_attr_fan3_input.dev_attr); continue;
device_create_file(&pdev->dev, err = device_create_file(&pdev->dev,
&sensor_dev_attr_fan3_min.dev_attr); &f71805f_fan_attr[i].dev_attr);
if (err)
goto exit_class;
} }
device_create_file(&pdev->dev,
&sensor_dev_attr_temp1_input.dev_attr);
device_create_file(&pdev->dev,
&sensor_dev_attr_temp2_input.dev_attr);
device_create_file(&pdev->dev,
&sensor_dev_attr_temp3_input.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr);
device_create_file(&pdev->dev,
&sensor_dev_attr_temp1_max_hyst.dev_attr);
device_create_file(&pdev->dev,
&sensor_dev_attr_temp2_max_hyst.dev_attr);
device_create_file(&pdev->dev,
&sensor_dev_attr_temp3_max_hyst.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr);
device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr);
device_create_file(&pdev->dev, &dev_attr_alarms_in);
device_create_file(&pdev->dev, &dev_attr_alarms_fan);
device_create_file(&pdev->dev, &dev_attr_alarms_temp);
device_create_file(&pdev->dev, &dev_attr_name);
return 0; return 0;
exit_class:
dev_err(&pdev->dev, "Sysfs interface creation failed\n");
hwmon_device_unregister(data->class_dev);
exit_free: exit_free:
kfree(data); kfree(data);
exit: exit:

View File

@@ -33,6 +33,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* /*
* Addresses to scan * Addresses to scan
@@ -133,7 +134,7 @@ static struct i2c_driver fscher_driver = {
struct fscher_data { struct fscher_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -332,7 +333,7 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
* global list */ * global list */
strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); strlcpy(new_client->name, "fscher", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -417,7 +418,7 @@ static struct fscher_data *fscher_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct fscher_data *data = i2c_get_clientdata(client); struct fscher_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
@@ -457,7 +458,7 @@ static struct fscher_data *fscher_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }
@@ -472,10 +473,10 @@ static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *dat
/* bits 0..1, 3..7 reserved => mask with 0x04 */ /* bits 0..1, 3..7 reserved => mask with 0x04 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v;
fscher_write_value(client, reg, v); fscher_write_value(client, reg, v);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -490,10 +491,10 @@ static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data,
{ {
unsigned long v = simple_strtoul(buf, NULL, 10); unsigned long v = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v;
fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -518,14 +519,14 @@ static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data,
return -EINVAL; return -EINVAL;
} }
down(&data->update_lock); mutex_lock(&data->update_lock);
/* bits 2..7 reserved => mask with 0x03 */ /* bits 2..7 reserved => mask with 0x03 */
data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03;
data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v;
fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -552,10 +553,10 @@ static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *da
/* bits 2..7 reserved, 0 read only => mask with 0x02 */ /* bits 2..7 reserved, 0 read only => mask with 0x02 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v;
fscher_write_value(client, reg, v); fscher_write_value(client, reg, v);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -609,10 +610,10 @@ static ssize_t set_control(struct i2c_client *client, struct fscher_data *data,
/* bits 1..7 reserved => mask with 0x01 */ /* bits 1..7 reserved => mask with 0x01 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->global_control &= ~v; data->global_control &= ~v;
fscher_write_value(client, reg, v); fscher_write_value(client, reg, v);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -631,11 +632,11 @@ static ssize_t set_watchdog_control(struct i2c_client *client, struct
/* bits 0..3 reserved => mask with 0xf0 */ /* bits 0..3 reserved => mask with 0xf0 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->watchdog[2] &= ~0xf0; data->watchdog[2] &= ~0xf0;
data->watchdog[2] |= v; data->watchdog[2] |= v;
fscher_write_value(client, reg, data->watchdog[2]); fscher_write_value(client, reg, data->watchdog[2]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -651,10 +652,10 @@ static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data
/* bits 0, 2..7 reserved => mask with 0x02 */ /* bits 0, 2..7 reserved => mask with 0x02 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->watchdog[1] &= ~v; data->watchdog[1] &= ~v;
fscher_write_value(client, reg, v); fscher_write_value(client, reg, v);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -669,10 +670,10 @@ static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data
{ {
unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->watchdog[0] = v; data->watchdog[0] = v;
fscher_write_value(client, reg, data->watchdog[0]); fscher_write_value(client, reg, data->watchdog[0]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }

View File

@@ -37,6 +37,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* /*
* Addresses to scan * Addresses to scan
@@ -89,8 +90,8 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter);
static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind);
static int fscpos_detach_client(struct i2c_client *client); static int fscpos_detach_client(struct i2c_client *client);
static int fscpos_read_value(struct i2c_client *client, u8 register); static int fscpos_read_value(struct i2c_client *client, u8 reg);
static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value); static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value);
static struct fscpos_data *fscpos_update_device(struct device *dev); static struct fscpos_data *fscpos_update_device(struct device *dev);
static void fscpos_init_client(struct i2c_client *client); static void fscpos_init_client(struct i2c_client *client);
@@ -114,7 +115,7 @@ static struct i2c_driver fscpos_driver = {
struct fscpos_data { struct fscpos_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* 0 until following fields are valid */ char valid; /* 0 until following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -208,13 +209,13 @@ static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data
return -EINVAL; return -EINVAL;
} }
down(&data->update_lock); mutex_lock(&data->update_lock);
/* bits 2..7 reserved => mask with 0x03 */ /* bits 2..7 reserved => mask with 0x03 */
data->fan_ripple[nr - 1] &= ~0x03; data->fan_ripple[nr - 1] &= ~0x03;
data->fan_ripple[nr - 1] |= v; data->fan_ripple[nr - 1] |= v;
fscpos_write_value(client, reg, data->fan_ripple[nr - 1]); fscpos_write_value(client, reg, data->fan_ripple[nr - 1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -232,10 +233,10 @@ static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data,
if (v < 0) v = 0; if (v < 0) v = 0;
if (v > 255) v = 255; if (v > 255) v = 255;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[nr - 1] = v; data->pwm[nr - 1] = v;
fscpos_write_value(client, reg, data->pwm[nr - 1]); fscpos_write_value(client, reg, data->pwm[nr - 1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -278,11 +279,11 @@ static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data
/* bits 0..3 reserved => mask with 0xf0 */ /* bits 0..3 reserved => mask with 0xf0 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->wdog_control &= ~0xf0; data->wdog_control &= ~0xf0;
data->wdog_control |= v; data->wdog_control |= v;
fscpos_write_value(client, reg, data->wdog_control); fscpos_write_value(client, reg, data->wdog_control);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -304,10 +305,10 @@ static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data
return -EINVAL; return -EINVAL;
} }
down(&data->update_lock); mutex_lock(&data->update_lock);
data->wdog_state &= ~v; data->wdog_state &= ~v;
fscpos_write_value(client, reg, v); fscpos_write_value(client, reg, v);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -321,10 +322,10 @@ static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data
{ {
unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->wdog_preset = v; data->wdog_preset = v;
fscpos_write_value(client, reg, data->wdog_preset); fscpos_write_value(client, reg, data->wdog_preset);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -483,7 +484,7 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE); strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -579,7 +580,7 @@ static struct fscpos_data *fscpos_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct fscpos_data *data = i2c_get_clientdata(client); struct fscpos_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
int i; int i;
@@ -625,7 +626,7 @@ static struct fscpos_data *fscpos_update_device(struct device *dev)
data->last_updated = jiffies; data->last_updated = jiffies;
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -43,6 +43,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
@@ -120,7 +121,7 @@ struct gl518_data {
struct class_device *class_dev; struct class_device *class_dev;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -212,10 +213,10 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c
struct gl518_data *data = i2c_get_clientdata(client); \ struct gl518_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = type##_TO_REG(val); \ data->value = type##_TO_REG(val); \
gl518_write_value(client, reg, data->value); \ gl518_write_value(client, reg, data->value); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
@@ -228,12 +229,12 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c
int regvalue; \ int regvalue; \
unsigned long val = simple_strtoul(buf, NULL, 10); \ unsigned long val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
regvalue = gl518_read_value(client, reg); \ regvalue = gl518_read_value(client, reg); \
data->value = type##_TO_REG(val); \ data->value = type##_TO_REG(val); \
regvalue = (regvalue & ~mask) | (data->value << shift); \ regvalue = (regvalue & ~mask) | (data->value << shift); \
gl518_write_value(client, reg, regvalue); \ gl518_write_value(client, reg, regvalue); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
@@ -265,7 +266,7 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c
int regvalue; int regvalue;
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT);
data->fan_min[0] = FAN_TO_REG(val, data->fan_min[0] = FAN_TO_REG(val,
DIV_FROM_REG(data->fan_div[0])); DIV_FROM_REG(data->fan_div[0]));
@@ -280,7 +281,7 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c
data->beep_mask &= data->alarm_mask; data->beep_mask &= data->alarm_mask;
gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -291,7 +292,7 @@ static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, c
int regvalue; int regvalue;
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT);
data->fan_min[1] = FAN_TO_REG(val, data->fan_min[1] = FAN_TO_REG(val,
DIV_FROM_REG(data->fan_div[1])); DIV_FROM_REG(data->fan_div[1]));
@@ -306,7 +307,7 @@ static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, c
data->beep_mask &= data->alarm_mask; data->beep_mask &= data->alarm_mask;
gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -407,7 +408,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE); strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE);
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -525,7 +526,7 @@ static struct gl518_data *gl518_update_device(struct device *dev)
struct gl518_data *data = i2c_get_clientdata(client); struct gl518_data *data = i2c_get_clientdata(client);
int val; int val;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -586,7 +587,7 @@ static struct gl518_data *gl518_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -29,6 +29,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Type of the extra sensor */ /* Type of the extra sensor */
static unsigned short extra_sensor_type; static unsigned short extra_sensor_type;
@@ -121,7 +122,7 @@ static struct i2c_driver gl520_driver = {
struct gl520_data { struct gl520_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until the following fields are valid */ char valid; /* zero until the following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -303,7 +304,7 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co
long v = simple_strtol(buf, NULL, 10); long v = simple_strtol(buf, NULL, 10);
u8 r; u8 r;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (n == 0) if (n == 0)
r = VDD_TO_REG(v); r = VDD_TO_REG(v);
@@ -317,7 +318,7 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co
else else
gl520_write_value(client, reg, r); gl520_write_value(client, reg, r);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -331,7 +332,7 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co
else else
r = IN_TO_REG(v); r = IN_TO_REG(v);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[n] = r; data->in_max[n] = r;
@@ -340,7 +341,7 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co
else else
gl520_write_value(client, reg, r); gl520_write_value(client, reg, r);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -373,7 +374,7 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c
unsigned long v = simple_strtoul(buf, NULL, 10); unsigned long v = simple_strtoul(buf, NULL, 10);
u8 r; u8 r;
down(&data->update_lock); mutex_lock(&data->update_lock);
r = FAN_TO_REG(v, data->fan_div[n - 1]); r = FAN_TO_REG(v, data->fan_div[n - 1]);
data->fan_min[n - 1] = r; data->fan_min[n - 1] = r;
@@ -390,7 +391,7 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c
data->beep_mask &= data->alarm_mask; data->beep_mask &= data->alarm_mask;
gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -409,7 +410,7 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c
return -EINVAL; return -EINVAL;
} }
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_div[n - 1] = r; data->fan_div[n - 1] = r;
if (n == 1) if (n == 1)
@@ -417,7 +418,7 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c
else else
gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4)); gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -425,10 +426,10 @@ static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, c
{ {
u8 r = simple_strtoul(buf, NULL, 10)?1:0; u8 r = simple_strtoul(buf, NULL, 10)?1:0;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_off = r; data->fan_off = r;
gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2)); gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -454,10 +455,10 @@ static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data,
{ {
long v = simple_strtol(buf, NULL, 10); long v = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[n - 1] = TEMP_TO_REG(v);; data->temp_max[n - 1] = TEMP_TO_REG(v);;
gl520_write_value(client, reg, data->temp_max[n - 1]); gl520_write_value(client, reg, data->temp_max[n - 1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -465,10 +466,10 @@ static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *d
{ {
long v = simple_strtol(buf, NULL, 10); long v = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max_hyst[n - 1] = TEMP_TO_REG(v); data->temp_max_hyst[n - 1] = TEMP_TO_REG(v);
gl520_write_value(client, reg, data->temp_max_hyst[n - 1]); gl520_write_value(client, reg, data->temp_max_hyst[n - 1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -491,10 +492,10 @@ static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *dat
{ {
u8 r = simple_strtoul(buf, NULL, 10)?0:1; u8 r = simple_strtoul(buf, NULL, 10)?0:1;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->beep_enable = !r; data->beep_enable = !r;
gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2)); gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -502,11 +503,11 @@ static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data,
{ {
u8 r = simple_strtoul(buf, NULL, 10); u8 r = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
r &= data->alarm_mask; r &= data->alarm_mask;
data->beep_mask = r; data->beep_mask = r;
gl520_write_value(client, reg, r); gl520_write_value(client, reg, r);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -561,7 +562,7 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields */ /* Fill in the remaining client fields */
strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE); strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -685,7 +686,7 @@ static struct gl520_data *gl520_update_device(struct device *dev)
struct gl520_data *data = i2c_get_clientdata(client); struct gl520_data *data = i2c_get_clientdata(client);
int val; int val;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
@@ -750,7 +751,7 @@ static struct gl520_data *gl520_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -33,6 +33,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
@@ -70,10 +71,10 @@ static u8 km_activity;
static int rest_x; static int rest_x;
static int rest_y; static int rest_y;
static DECLARE_MUTEX(hdaps_sem); static DEFINE_MUTEX(hdaps_mutex);
/* /*
* __get_latch - Get the value from a given port. Callers must hold hdaps_sem. * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex.
*/ */
static inline u8 __get_latch(u16 port) static inline u8 __get_latch(u16 port)
{ {
@@ -82,7 +83,7 @@ static inline u8 __get_latch(u16 port)
/* /*
* __check_latch - Check a port latch for a given value. Returns zero if the * __check_latch - Check a port latch for a given value. Returns zero if the
* port contains the given value. Callers must hold hdaps_sem. * port contains the given value. Callers must hold hdaps_mutex.
*/ */
static inline int __check_latch(u16 port, u8 val) static inline int __check_latch(u16 port, u8 val)
{ {
@@ -93,7 +94,7 @@ static inline int __check_latch(u16 port, u8 val)
/* /*
* __wait_latch - Wait up to 100us for a port latch to get a certain value, * __wait_latch - Wait up to 100us for a port latch to get a certain value,
* returning zero if the value is obtained. Callers must hold hdaps_sem. * returning zero if the value is obtained. Callers must hold hdaps_mutex.
*/ */
static int __wait_latch(u16 port, u8 val) static int __wait_latch(u16 port, u8 val)
{ {
@@ -110,7 +111,7 @@ static int __wait_latch(u16 port, u8 val)
/* /*
* __device_refresh - request a refresh from the accelerometer. Does not wait * __device_refresh - request a refresh from the accelerometer. Does not wait
* for refresh to complete. Callers must hold hdaps_sem. * for refresh to complete. Callers must hold hdaps_mutex.
*/ */
static void __device_refresh(void) static void __device_refresh(void)
{ {
@@ -124,7 +125,7 @@ static void __device_refresh(void)
/* /*
* __device_refresh_sync - request a synchronous refresh from the * __device_refresh_sync - request a synchronous refresh from the
* accelerometer. We wait for the refresh to complete. Returns zero if * accelerometer. We wait for the refresh to complete. Returns zero if
* successful and nonzero on error. Callers must hold hdaps_sem. * successful and nonzero on error. Callers must hold hdaps_mutex.
*/ */
static int __device_refresh_sync(void) static int __device_refresh_sync(void)
{ {
@@ -134,7 +135,7 @@ static int __device_refresh_sync(void)
/* /*
* __device_complete - indicate to the accelerometer that we are done reading * __device_complete - indicate to the accelerometer that we are done reading
* data, and then initiate an async refresh. Callers must hold hdaps_sem. * data, and then initiate an async refresh. Callers must hold hdaps_mutex.
*/ */
static inline void __device_complete(void) static inline void __device_complete(void)
{ {
@@ -152,7 +153,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
{ {
int ret; int ret;
down(&hdaps_sem); mutex_lock(&hdaps_mutex);
/* do a sync refresh -- we need to be sure that we read fresh data */ /* do a sync refresh -- we need to be sure that we read fresh data */
ret = __device_refresh_sync(); ret = __device_refresh_sync();
@@ -163,7 +164,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
__device_complete(); __device_complete();
out: out:
up(&hdaps_sem); mutex_unlock(&hdaps_mutex);
return ret; return ret;
} }
@@ -198,9 +199,9 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2,
{ {
int ret; int ret;
down(&hdaps_sem); mutex_lock(&hdaps_mutex);
ret = __hdaps_read_pair(port1, port2, val1, val2); ret = __hdaps_read_pair(port1, port2, val1, val2);
up(&hdaps_sem); mutex_unlock(&hdaps_mutex);
return ret; return ret;
} }
@@ -213,7 +214,7 @@ static int hdaps_device_init(void)
{ {
int total, ret = -ENXIO; int total, ret = -ENXIO;
down(&hdaps_sem); mutex_lock(&hdaps_mutex);
outb(0x13, 0x1610); outb(0x13, 0x1610);
outb(0x01, 0x161f); outb(0x01, 0x161f);
@@ -279,7 +280,7 @@ static int hdaps_device_init(void)
} }
out: out:
up(&hdaps_sem); mutex_unlock(&hdaps_mutex);
return ret; return ret;
} }
@@ -313,7 +314,7 @@ static struct platform_driver hdaps_driver = {
}; };
/* /*
* hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex.
*/ */
static void hdaps_calibrate(void) static void hdaps_calibrate(void)
{ {
@@ -325,7 +326,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
int x, y; int x, y;
/* Cannot sleep. Try nonblockingly. If we fail, try again later. */ /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
if (down_trylock(&hdaps_sem)) { if (!mutex_trylock(&hdaps_mutex)) {
mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
return; return;
} }
@@ -340,7 +341,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
out: out:
up(&hdaps_sem); mutex_unlock(&hdaps_mutex);
} }
@@ -420,9 +421,9 @@ static ssize_t hdaps_calibrate_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
down(&hdaps_sem); mutex_lock(&hdaps_mutex);
hdaps_calibrate(); hdaps_calibrate();
up(&hdaps_sem); mutex_unlock(&hdaps_mutex);
return count; return count;
} }

View File

@@ -54,6 +54,10 @@
(IMVP-II). You can find more information in the datasheet of Max1718 (IMVP-II). You can find more information in the datasheet of Max1718
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452 http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452
The 13 specification corresponds to the Intel Pentium M series. There
doesn't seem to be any named specification for these. The conversion
tables are detailed directly in the various Pentium M datasheets:
http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm
*/ */
/* vrm is the VRM/VRD document version multiplied by 10. /* vrm is the VRM/VRD document version multiplied by 10.
@@ -100,6 +104,8 @@ int vid_from_reg(int val, u8 vrm)
case 17: /* Intel IMVP-II */ case 17: /* Intel IMVP-II */
return(val & 0x10 ? 975 - (val & 0xF) * 25 : return(val & 0x10 ? 975 - (val & 0xF) * 25 :
1750 - val * 50); 1750 - val * 50);
case 13:
return(1708 - (val & 0x3f) * 16);
default: /* report 0 for unknown */ default: /* report 0 for unknown */
printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
return 0; return 0;
@@ -129,8 +135,9 @@ struct vrm_model {
static struct vrm_model vrm_models[] = { static struct vrm_model vrm_models[] = {
{X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */ {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */
{X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */ {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */
{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */ {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */
{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */
{X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */
{X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */
{X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */

View File

@@ -17,6 +17,7 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/spinlock.h>
#define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_PREFIX "hwmon"
#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
@@ -24,6 +25,7 @@
static struct class *hwmon_class; static struct class *hwmon_class;
static DEFINE_IDR(hwmon_idr); static DEFINE_IDR(hwmon_idr);
static DEFINE_SPINLOCK(idr_lock);
/** /**
* hwmon_device_register - register w/ hwmon sysfs class * hwmon_device_register - register w/ hwmon sysfs class
@@ -37,20 +39,30 @@ static DEFINE_IDR(hwmon_idr);
struct class_device *hwmon_device_register(struct device *dev) struct class_device *hwmon_device_register(struct device *dev)
{ {
struct class_device *cdev; struct class_device *cdev;
int id; int id, err;
if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0) again:
if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0))
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (idr_get_new(&hwmon_idr, NULL, &id) < 0) spin_lock(&idr_lock);
return ERR_PTR(-ENOMEM); err = idr_get_new(&hwmon_idr, NULL, &id);
spin_unlock(&idr_lock);
if (unlikely(err == -EAGAIN))
goto again;
else if (unlikely(err))
return ERR_PTR(err);
id = id & MAX_ID_MASK; id = id & MAX_ID_MASK;
cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev,
HWMON_ID_FORMAT, id); HWMON_ID_FORMAT, id);
if (IS_ERR(cdev)) if (IS_ERR(cdev)) {
spin_lock(&idr_lock);
idr_remove(&hwmon_idr, id); idr_remove(&hwmon_idr, id);
spin_unlock(&idr_lock);
}
return cdev; return cdev;
} }
@@ -64,9 +76,11 @@ void hwmon_device_unregister(struct class_device *cdev)
{ {
int id; int id;
if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) { if (likely(sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1)) {
class_device_unregister(cdev); class_device_unregister(cdev);
spin_lock(&idr_lock);
idr_remove(&hwmon_idr, id); idr_remove(&hwmon_idr, id);
spin_unlock(&idr_lock);
} else } else
dev_dbg(cdev->dev, dev_dbg(cdev->dev,
"hwmon_device_unregister() failed: bad class ID!\n"); "hwmon_device_unregister() failed: bad class ID!\n");

View File

@@ -41,6 +41,7 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
@@ -194,10 +195,10 @@ static int DIV_TO_REG(int val)
struct it87_data { struct it87_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -224,9 +225,8 @@ static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
static int it87_detect(struct i2c_adapter *adapter, int address, int kind); static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
static int it87_detach_client(struct i2c_client *client); static int it87_detach_client(struct i2c_client *client);
static int it87_read_value(struct i2c_client *client, u8 register); static int it87_read_value(struct i2c_client *client, u8 reg);
static int it87_write_value(struct i2c_client *client, u8 register, static int it87_write_value(struct i2c_client *client, u8 reg, u8 value);
u8 value);
static struct it87_data *it87_update_device(struct device *dev); static struct it87_data *it87_update_device(struct device *dev);
static int it87_check_pwm(struct i2c_client *client); static int it87_check_pwm(struct i2c_client *client);
static void it87_init_client(struct i2c_client *client, struct it87_data *data); static void it87_init_client(struct i2c_client *client, struct it87_data *data);
@@ -290,11 +290,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = IN_TO_REG(val); data->in_min[nr] = IN_TO_REG(val);
it87_write_value(client, IT87_REG_VIN_MIN(nr), it87_write_value(client, IT87_REG_VIN_MIN(nr),
data->in_min[nr]); data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
@@ -307,11 +307,11 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = IN_TO_REG(val); data->in_max[nr] = IN_TO_REG(val);
it87_write_value(client, IT87_REG_VIN_MAX(nr), it87_write_value(client, IT87_REG_VIN_MAX(nr),
data->in_max[nr]); data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -381,10 +381,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_high[nr] = TEMP_TO_REG(val); data->temp_high[nr] = TEMP_TO_REG(val);
it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
@@ -397,10 +397,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_low[nr] = TEMP_TO_REG(val); data->temp_low[nr] = TEMP_TO_REG(val);
it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_temp_offset(offset) \ #define show_temp_offset(offset) \
@@ -440,7 +440,7 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->sensor &= ~(1 << nr); data->sensor &= ~(1 << nr);
data->sensor &= ~(8 << nr); data->sensor &= ~(8 << nr);
@@ -450,11 +450,11 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
else if (val == 2) else if (val == 2)
data->sensor |= 8 << nr; data->sensor |= 8 << nr;
else if (val != 0) { else if (val != 0) {
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_sensor_offset(offset) \ #define show_sensor_offset(offset) \
@@ -524,7 +524,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); u8 reg = it87_read_value(client, IT87_REG_FAN_DIV);
down(&data->update_lock); mutex_lock(&data->update_lock);
switch (nr) { switch (nr) {
case 0: data->fan_div[nr] = reg & 0x07; break; case 0: data->fan_div[nr] = reg & 0x07; break;
case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
@@ -533,7 +533,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
@@ -548,7 +548,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
int i, min[3]; int i, min[3];
u8 old; u8 old;
down(&data->update_lock); mutex_lock(&data->update_lock);
old = it87_read_value(client, IT87_REG_FAN_DIV); old = it87_read_value(client, IT87_REG_FAN_DIV);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
@@ -576,7 +576,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i]));
it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]);
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_pwm_enable(struct device *dev, static ssize_t set_pwm_enable(struct device *dev,
@@ -589,7 +589,7 @@ static ssize_t set_pwm_enable(struct device *dev,
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (val == 0) { if (val == 0) {
int tmp; int tmp;
@@ -606,11 +606,11 @@ static ssize_t set_pwm_enable(struct device *dev,
/* set saved pwm value, clear FAN_CTLX PWM mode bit */ /* set saved pwm value, clear FAN_CTLX PWM mode bit */
it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
} else { } else {
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
@@ -626,11 +626,11 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
if (val < 0 || val > 255) if (val < 0 || val > 255)
return -EINVAL; return -EINVAL;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->manual_pwm_ctl[nr] = val; data->manual_pwm_ctl[nr] = val;
if (data->fan_main_ctrl & (1 << nr)) if (data->fan_main_ctrl & (1 << nr))
it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -776,7 +776,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
new_client = &data->client; new_client = &data->client;
if (is_isa) if (is_isa)
init_MUTEX(&data->lock); mutex_init(&data->lock);
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
new_client->adapter = adapter; new_client->adapter = adapter;
@@ -823,7 +823,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -950,10 +950,10 @@ static int it87_read_value(struct i2c_client *client, u8 reg)
int res; int res;
if (i2c_is_isa_client(client)) { if (i2c_is_isa_client(client)) {
down(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
res = inb_p(client->addr + IT87_DATA_REG_OFFSET); res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} else } else
return i2c_smbus_read_byte_data(client, reg); return i2c_smbus_read_byte_data(client, reg);
@@ -969,10 +969,10 @@ static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
if (i2c_is_isa_client(client)) { if (i2c_is_isa_client(client)) {
down(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
outb_p(value, client->addr + IT87_DATA_REG_OFFSET); outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return 0; return 0;
} else } else
return i2c_smbus_write_byte_data(client, reg, value); return i2c_smbus_write_byte_data(client, reg, value);
@@ -1098,7 +1098,7 @@ static struct it87_data *it87_update_device(struct device *dev)
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -1160,7 +1160,7 @@ static struct it87_data *it87_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -45,6 +45,7 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* /*
* Addresses to scan * Addresses to scan
@@ -153,7 +154,7 @@ static struct i2c_driver lm63_driver = {
struct lm63_data { struct lm63_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -192,13 +193,13 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan[1] = FAN_TO_REG(val); data->fan[1] = FAN_TO_REG(val);
i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
data->fan[1] & 0xFF); data->fan[1] & 0xFF);
i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
data->fan[1] >> 8); data->fan[1] >> 8);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -222,12 +223,12 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
return -EPERM; return -EPERM;
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm1_value = val <= 0 ? 0 : data->pwm1_value = val <= 0 ? 0 :
val >= 255 ? 2 * data->pwm1_freq : val >= 255 ? 2 * data->pwm1_freq :
(val * data->pwm1_freq * 2 + 127) / 255; (val * data->pwm1_freq * 2 + 127) / 255;
i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value); i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -253,10 +254,10 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy,
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp8[1] = TEMP8_TO_REG(val); data->temp8[1] = TEMP8_TO_REG(val);
i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]); i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -284,13 +285,13 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
int nr = attr->index; int nr = attr->index;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp11[nr] = TEMP11_TO_REG(val); data->temp11[nr] = TEMP11_TO_REG(val);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
data->temp11[nr] >> 8); data->temp11[nr] >> 8);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
data->temp11[nr] & 0xff); data->temp11[nr] & 0xff);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -314,11 +315,11 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
long hyst; long hyst;
down(&data->update_lock); mutex_lock(&data->update_lock);
hyst = TEMP8_FROM_REG(data->temp8[2]) - val; hyst = TEMP8_FROM_REG(data->temp8[2]) - val;
i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
HYST_TO_REG(hyst)); HYST_TO_REG(hyst));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -427,7 +428,7 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); strlcpy(new_client->name, "lm63", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -530,7 +531,7 @@ static struct lm63_data *lm63_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
if (data->config & 0x04) { /* tachometer enabled */ if (data->config & 0x04) { /* tachometer enabled */
@@ -582,7 +583,7 @@ static struct lm63_data *lm63_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -25,6 +25,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include "lm75.h" #include "lm75.h"
@@ -47,7 +48,7 @@ I2C_CLIENT_INSMOD_1(lm75);
struct lm75_data { struct lm75_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
u16 temp_input; /* Register values */ u16 temp_input; /* Register values */
@@ -91,10 +92,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
struct lm75_data *data = i2c_get_clientdata(client); \ struct lm75_data *data = i2c_get_clientdata(client); \
int temp = simple_strtoul(buf, NULL, 10); \ int temp = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = LM75_TEMP_TO_REG(temp); \ data->value = LM75_TEMP_TO_REG(temp); \
lm75_write_value(client, reg, data->value); \ lm75_write_value(client, reg, data->value); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
set(temp_max, LM75_REG_TEMP_OS); set(temp_max, LM75_REG_TEMP_OS);
@@ -188,7 +189,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */ /* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -264,7 +265,7 @@ static struct lm75_data *lm75_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm75_data *data = i2c_get_clientdata(client); struct lm75_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -277,7 +278,7 @@ static struct lm75_data *lm75_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -32,6 +32,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END }; static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END };
@@ -51,7 +52,7 @@ I2C_CLIENT_INSMOD_1(lm77);
struct lm77_data { struct lm77_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; char valid;
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
int temp_input; /* Temperatures */ int temp_input; /* Temperatures */
@@ -139,10 +140,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
struct lm77_data *data = i2c_get_clientdata(client); \ struct lm77_data *data = i2c_get_clientdata(client); \
long val = simple_strtoul(buf, NULL, 10); \ long val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = val; \ data->value = val; \
lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value)); \ lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value)); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
@@ -157,11 +158,11 @@ static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *a
struct lm77_data *data = i2c_get_clientdata(client); struct lm77_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_hyst = data->temp_crit - val; data->temp_hyst = data->temp_crit - val;
lm77_write_value(client, LM77_REG_TEMP_HYST, lm77_write_value(client, LM77_REG_TEMP_HYST,
LM77_TEMP_TO_REG(data->temp_hyst)); LM77_TEMP_TO_REG(data->temp_hyst));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -173,7 +174,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
long val = simple_strtoul(buf, NULL, 10); long val = simple_strtoul(buf, NULL, 10);
int oldcrithyst; int oldcrithyst;
down(&data->update_lock); mutex_lock(&data->update_lock);
oldcrithyst = data->temp_crit - data->temp_hyst; oldcrithyst = data->temp_crit - data->temp_hyst;
data->temp_crit = val; data->temp_crit = val;
data->temp_hyst = data->temp_crit - oldcrithyst; data->temp_hyst = data->temp_crit - oldcrithyst;
@@ -181,7 +182,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
LM77_TEMP_TO_REG(data->temp_crit)); LM77_TEMP_TO_REG(data->temp_crit));
lm77_write_value(client, LM77_REG_TEMP_HYST, lm77_write_value(client, LM77_REG_TEMP_HYST,
LM77_TEMP_TO_REG(data->temp_hyst)); LM77_TEMP_TO_REG(data->temp_hyst));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -306,7 +307,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */ /* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -380,7 +381,7 @@ static struct lm77_data *lm77_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm77_data *data = i2c_get_clientdata(client); struct lm77_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -406,7 +407,7 @@ static struct lm77_data *lm77_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -27,6 +27,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
/* Addresses to scan */ /* Addresses to scan */
@@ -131,10 +132,10 @@ static inline int TEMP_FROM_REG(s8 val)
struct lm78_data { struct lm78_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -157,8 +158,8 @@ static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
static int lm78_detach_client(struct i2c_client *client); static int lm78_detach_client(struct i2c_client *client);
static int lm78_read_value(struct i2c_client *client, u8 register); static int lm78_read_value(struct i2c_client *client, u8 reg);
static int lm78_write_value(struct i2c_client *client, u8 register, u8 value); static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value);
static struct lm78_data *lm78_update_device(struct device *dev); static struct lm78_data *lm78_update_device(struct device *dev);
static void lm78_init_client(struct i2c_client *client); static void lm78_init_client(struct i2c_client *client);
@@ -207,10 +208,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = IN_TO_REG(val); data->in_min[nr] = IN_TO_REG(val);
lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]); lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -221,10 +222,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = IN_TO_REG(val); data->in_max[nr] = IN_TO_REG(val);
lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]); lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -288,10 +289,10 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr,
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_over = TEMP_TO_REG(val); data->temp_over = TEMP_TO_REG(val);
lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over); lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -307,10 +308,10 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr,
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_hyst = TEMP_TO_REG(val); data->temp_hyst = TEMP_TO_REG(val);
lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst); lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -342,10 +343,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -368,7 +369,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
unsigned long min; unsigned long min;
u8 reg; u8 reg;
down(&data->update_lock); mutex_lock(&data->update_lock);
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])); DIV_FROM_REG(data->fan_div[nr]));
@@ -380,7 +381,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
default: default:
dev_err(&client->dev, "fan_div value %ld not " dev_err(&client->dev, "fan_div value %ld not "
"supported. Choose one of 1, 2, 4 or 8!\n", val); "supported. Choose one of 1, 2, 4 or 8!\n", val);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
@@ -398,7 +399,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
data->fan_min[nr] = data->fan_min[nr] =
FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -548,7 +549,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
new_client = &data->client; new_client = &data->client;
if (is_isa) if (is_isa)
init_MUTEX(&data->lock); mutex_init(&data->lock);
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
new_client->adapter = adapter; new_client->adapter = adapter;
@@ -598,7 +599,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -697,10 +698,10 @@ static int lm78_read_value(struct i2c_client *client, u8 reg)
int res; int res;
if (i2c_is_isa_client(client)) { if (i2c_is_isa_client(client)) {
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
down(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
res = inb_p(client->addr + LM78_DATA_REG_OFFSET); res = inb_p(client->addr + LM78_DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} else } else
return i2c_smbus_read_byte_data(client, reg); return i2c_smbus_read_byte_data(client, reg);
@@ -717,10 +718,10 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
{ {
if (i2c_is_isa_client(client)) { if (i2c_is_isa_client(client)) {
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
down(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
outb_p(value, client->addr + LM78_DATA_REG_OFFSET); outb_p(value, client->addr + LM78_DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return 0; return 0;
} else } else
return i2c_smbus_write_byte_data(client, reg, value); return i2c_smbus_write_byte_data(client, reg, value);
@@ -742,7 +743,7 @@ static struct lm78_data *lm78_update_device(struct device *dev)
struct lm78_data *data = i2c_get_clientdata(client); struct lm78_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -786,7 +787,7 @@ static struct lm78_data *lm78_update_device(struct device *dev)
data->fan_div[2] = 1; data->fan_div[2] = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -28,6 +28,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c,
@@ -108,7 +109,7 @@ static inline long TEMP_FROM_REG(u16 temp)
struct lm80_data { struct lm80_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -191,10 +192,10 @@ static ssize_t set_in_##suffix(struct device *dev, struct device_attribute *attr
struct lm80_data *data = i2c_get_clientdata(client); \ struct lm80_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock);\ mutex_lock(&data->update_lock);\
data->value = IN_TO_REG(val); \ data->value = IN_TO_REG(val); \
lm80_write_value(client, reg, data->value); \ lm80_write_value(client, reg, data->value); \
up(&data->update_lock);\ mutex_unlock(&data->update_lock);\
return count; \ return count; \
} }
set_in(min0, in_min[0], LM80_REG_IN_MIN(0)); set_in(min0, in_min[0], LM80_REG_IN_MIN(0));
@@ -241,10 +242,10 @@ static ssize_t set_fan_##suffix(struct device *dev, struct device_attribute *att
struct lm80_data *data = i2c_get_clientdata(client); \ struct lm80_data *data = i2c_get_clientdata(client); \
long val = simple_strtoul(buf, NULL, 10); \ long val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock);\ mutex_lock(&data->update_lock);\
data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \ data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \
lm80_write_value(client, reg, data->value); \ lm80_write_value(client, reg, data->value); \
up(&data->update_lock);\ mutex_unlock(&data->update_lock);\
return count; \ return count; \
} }
set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]); set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]);
@@ -263,7 +264,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
u8 reg; u8 reg;
/* Save fan_min */ /* Save fan_min */
down(&data->update_lock); mutex_lock(&data->update_lock);
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])); DIV_FROM_REG(data->fan_div[nr]));
@@ -275,7 +276,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
default: default:
dev_err(&client->dev, "fan_div value %ld not " dev_err(&client->dev, "fan_div value %ld not "
"supported. Choose one of 1, 2, 4 or 8!\n", val); "supported. Choose one of 1, 2, 4 or 8!\n", val);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
@@ -286,7 +287,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
/* Restore fan_min */ /* Restore fan_min */
data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -325,10 +326,10 @@ static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *at
struct lm80_data *data = i2c_get_clientdata(client); \ struct lm80_data *data = i2c_get_clientdata(client); \
long val = simple_strtoul(buf, NULL, 10); \ long val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = TEMP_LIMIT_TO_REG(val); \ data->value = TEMP_LIMIT_TO_REG(val); \
lm80_write_value(client, reg, data->value); \ lm80_write_value(client, reg, data->value); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX); set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX);
@@ -437,7 +438,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */ /* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -545,7 +546,7 @@ static struct lm80_data *lm80_update_device(struct device *dev)
struct lm80_data *data = i2c_get_clientdata(client); struct lm80_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
dev_dbg(&client->dev, "Starting lm80 update\n"); dev_dbg(&client->dev, "Starting lm80 update\n");
@@ -585,7 +586,7 @@ static struct lm80_data *lm80_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -35,6 +35,7 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* /*
* Addresses to scan * Addresses to scan
@@ -139,7 +140,7 @@ static struct i2c_driver lm83_driver = {
struct lm83_data { struct lm83_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -171,11 +172,11 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
int nr = attr->index; int nr = attr->index;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp[nr] = TEMP_TO_REG(val); data->temp[nr] = TEMP_TO_REG(val);
i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4],
data->temp[nr]); data->temp[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -300,7 +301,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */ /* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -373,7 +374,7 @@ static struct lm83_data *lm83_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm83_data *data = i2c_get_clientdata(client); struct lm83_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
int nr; int nr;
@@ -393,7 +394,7 @@ static struct lm83_data *lm83_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -31,6 +31,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
@@ -331,10 +332,10 @@ struct lm85_autofan {
struct lm85_data { struct lm85_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
int valid; /* !=0 if following fields are valid */ int valid; /* !=0 if following fields are valid */
unsigned long last_reading; /* In jiffies */ unsigned long last_reading; /* In jiffies */
unsigned long last_config; /* In jiffies */ unsigned long last_config; /* In jiffies */
@@ -373,8 +374,8 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
int kind); int kind);
static int lm85_detach_client(struct i2c_client *client); static int lm85_detach_client(struct i2c_client *client);
static int lm85_read_value(struct i2c_client *client, u8 register); static int lm85_read_value(struct i2c_client *client, u8 reg);
static int lm85_write_value(struct i2c_client *client, u8 register, int value); static int lm85_write_value(struct i2c_client *client, u8 reg, int value);
static struct lm85_data *lm85_update_device(struct device *dev); static struct lm85_data *lm85_update_device(struct device *dev);
static void lm85_init_client(struct i2c_client *client); static void lm85_init_client(struct i2c_client *client);
@@ -407,10 +408,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val); data->fan_min[nr] = FAN_TO_REG(val);
lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]); lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -499,10 +500,10 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[nr] = PWM_TO_REG(val); data->pwm[nr] = PWM_TO_REG(val);
lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]); lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
@@ -559,10 +560,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = INS_TO_REG(nr, val); data->in_min[nr] = INS_TO_REG(nr, val);
lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]); lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_in_max(struct device *dev, char *buf, int nr) static ssize_t show_in_max(struct device *dev, char *buf, int nr)
@@ -577,10 +578,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = INS_TO_REG(nr, val); data->in_max[nr] = INS_TO_REG(nr, val);
lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]); lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_in_reg(offset) \ #define show_in_reg(offset) \
@@ -640,10 +641,10 @@ static ssize_t set_temp_min(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_min[nr] = TEMP_TO_REG(val); data->temp_min[nr] = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_temp_max(struct device *dev, char *buf, int nr) static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
@@ -658,10 +659,10 @@ static ssize_t set_temp_max(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[nr] = TEMP_TO_REG(val); data->temp_max[nr] = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_temp_reg(offset) \ #define show_temp_reg(offset) \
@@ -713,12 +714,12 @@ static ssize_t set_pwm_auto_channels(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->autofan[nr].config = (data->autofan[nr].config & (~0xe0)) data->autofan[nr].config = (data->autofan[nr].config & (~0xe0))
| ZONE_TO_REG(val) ; | ZONE_TO_REG(val) ;
lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr),
data->autofan[nr].config); data->autofan[nr].config);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr) static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr)
@@ -733,11 +734,11 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->autofan[nr].min_pwm = PWM_TO_REG(val); data->autofan[nr].min_pwm = PWM_TO_REG(val);
lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr), lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr),
data->autofan[nr].min_pwm); data->autofan[nr].min_pwm);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr) static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr)
@@ -752,7 +753,7 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->autofan[nr].min_off = val; data->autofan[nr].min_off = val;
lm85_write_value(client, LM85_REG_AFAN_SPIKE1, data->smooth[0] lm85_write_value(client, LM85_REG_AFAN_SPIKE1, data->smooth[0]
| data->syncpwm3 | data->syncpwm3
@@ -760,7 +761,7 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf,
| (data->autofan[1].min_off ? 0x40 : 0) | (data->autofan[1].min_off ? 0x40 : 0)
| (data->autofan[2].min_off ? 0x80 : 0) | (data->autofan[2].min_off ? 0x80 : 0)
); );
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr) static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr)
@@ -775,13 +776,13 @@ static ssize_t set_pwm_auto_pwm_freq(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->autofan[nr].freq = FREQ_TO_REG(val); data->autofan[nr].freq = FREQ_TO_REG(val);
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
(data->zone[nr].range << 4) (data->zone[nr].range << 4)
| data->autofan[nr].freq | data->autofan[nr].freq
); );
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define pwm_auto(offset) \ #define pwm_auto(offset) \
@@ -857,7 +858,7 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf,
int min; int min;
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
min = TEMP_FROM_REG(data->zone[nr].limit); min = TEMP_FROM_REG(data->zone[nr].limit);
data->zone[nr].off_desired = TEMP_TO_REG(val); data->zone[nr].off_desired = TEMP_TO_REG(val);
data->zone[nr].hyst = HYST_TO_REG(min - val); data->zone[nr].hyst = HYST_TO_REG(min - val);
@@ -871,7 +872,7 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf,
(data->zone[2].hyst << 4) (data->zone[2].hyst << 4)
); );
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr) static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr)
@@ -886,7 +887,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->zone[nr].limit = TEMP_TO_REG(val); data->zone[nr].limit = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr), lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr),
data->zone[nr].limit); data->zone[nr].limit);
@@ -913,7 +914,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf,
(data->zone[2].hyst << 4) (data->zone[2].hyst << 4)
); );
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr) static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr)
@@ -930,7 +931,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf,
int min; int min;
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
min = TEMP_FROM_REG(data->zone[nr].limit); min = TEMP_FROM_REG(data->zone[nr].limit);
data->zone[nr].max_desired = TEMP_TO_REG(val); data->zone[nr].max_desired = TEMP_TO_REG(val);
data->zone[nr].range = RANGE_TO_REG( data->zone[nr].range = RANGE_TO_REG(
@@ -938,7 +939,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf,
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
((data->zone[nr].range & 0x0f) << 4) ((data->zone[nr].range & 0x0f) << 4)
| (data->autofan[nr].freq & 0x07)); | (data->autofan[nr].freq & 0x07));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr) static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr)
@@ -953,11 +954,11 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev, const char *buf,
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->zone[nr].critical = TEMP_TO_REG(val); data->zone[nr].critical = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr), lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr),
data->zone[nr].critical); data->zone[nr].critical);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define temp_auto(offset) \ #define temp_auto(offset) \
@@ -1149,7 +1150,7 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
/* Fill in the remaining client fields */ /* Fill in the remaining client fields */
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -1368,7 +1369,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if ( !data->valid || if ( !data->valid ||
time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) { time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) {
@@ -1571,7 +1572,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -60,6 +60,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* /*
* Addresses to scan * Addresses to scan
@@ -176,7 +177,7 @@ static struct i2c_driver lm87_driver = {
struct lm87_data { struct lm87_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -253,11 +254,11 @@ static void set_in_min(struct device *dev, const char *buf, int nr)
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]); data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]);
lm87_write_value(client, nr<6 ? LM87_REG_IN_MIN(nr) : lm87_write_value(client, nr<6 ? LM87_REG_IN_MIN(nr) :
LM87_REG_AIN_MIN(nr-6), data->in_min[nr]); LM87_REG_AIN_MIN(nr-6), data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
static void set_in_max(struct device *dev, const char *buf, int nr) static void set_in_max(struct device *dev, const char *buf, int nr)
@@ -266,11 +267,11 @@ static void set_in_max(struct device *dev, const char *buf, int nr)
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]); data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]);
lm87_write_value(client, nr<6 ? LM87_REG_IN_MAX(nr) : lm87_write_value(client, nr<6 ? LM87_REG_IN_MAX(nr) :
LM87_REG_AIN_MAX(nr-6), data->in_max[nr]); LM87_REG_AIN_MAX(nr-6), data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
#define set_in(offset) \ #define set_in(offset) \
@@ -327,10 +328,10 @@ static void set_temp_low(struct device *dev, const char *buf, int nr)
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_low[nr] = TEMP_TO_REG(val); data->temp_low[nr] = TEMP_TO_REG(val);
lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
static void set_temp_high(struct device *dev, const char *buf, int nr) static void set_temp_high(struct device *dev, const char *buf, int nr)
@@ -339,10 +340,10 @@ static void set_temp_high(struct device *dev, const char *buf, int nr)
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_high[nr] = TEMP_TO_REG(val); data->temp_high[nr] = TEMP_TO_REG(val);
lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
#define set_temp(offset) \ #define set_temp(offset) \
@@ -411,11 +412,11 @@ static void set_fan_min(struct device *dev, const char *buf, int nr)
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, data->fan_min[nr] = FAN_TO_REG(val,
FAN_DIV_FROM_REG(data->fan_div[nr])); FAN_DIV_FROM_REG(data->fan_div[nr]));
lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
/* Note: we save and restore the fan minimum here, because its value is /* Note: we save and restore the fan minimum here, because its value is
@@ -431,7 +432,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
unsigned long min; unsigned long min;
u8 reg; u8 reg;
down(&data->update_lock); mutex_lock(&data->update_lock);
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
FAN_DIV_FROM_REG(data->fan_div[nr])); FAN_DIV_FROM_REG(data->fan_div[nr]));
@@ -441,7 +442,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
case 4: data->fan_div[nr] = 2; break; case 4: data->fan_div[nr] = 2; break;
case 8: data->fan_div[nr] = 3; break; case 8: data->fan_div[nr] = 3; break;
default: default:
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
@@ -459,7 +460,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
data->fan_min[nr] = FAN_TO_REG(min, val); data->fan_min[nr] = FAN_TO_REG(min, val);
lm87_write_value(client, LM87_REG_FAN_MIN(nr), lm87_write_value(client, LM87_REG_FAN_MIN(nr),
data->fan_min[nr]); data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -522,10 +523,10 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->aout = AOUT_TO_REG(val); data->aout = AOUT_TO_REG(val);
lm87_write_value(client, LM87_REG_AOUT, data->aout); lm87_write_value(client, LM87_REG_AOUT, data->aout);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
@@ -589,7 +590,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */ /* We can fill in the remaining client fields */
strlcpy(new_client->name, "lm87", I2C_NAME_SIZE); strlcpy(new_client->name, "lm87", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -744,7 +745,7 @@ static struct lm87_data *lm87_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm87_data *data = i2c_get_clientdata(client); struct lm87_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
int i, j; int i, j;
@@ -813,7 +814,7 @@ static struct lm87_data *lm87_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -78,6 +78,7 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* /*
* Addresses to scan * Addresses to scan
@@ -201,7 +202,7 @@ static struct i2c_driver lm90_driver = {
struct lm90_data { struct lm90_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
int kind; int kind;
@@ -247,13 +248,13 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
int nr = attr->index; int nr = attr->index;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (data->kind == adt7461) if (data->kind == adt7461)
data->temp8[nr] = TEMP1_TO_REG_ADT7461(val); data->temp8[nr] = TEMP1_TO_REG_ADT7461(val);
else else
data->temp8[nr] = TEMP1_TO_REG(val); data->temp8[nr] = TEMP1_TO_REG(val);
i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]); i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -281,7 +282,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
int nr = attr->index; int nr = attr->index;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (data->kind == adt7461) if (data->kind == adt7461)
data->temp11[nr] = TEMP2_TO_REG_ADT7461(val); data->temp11[nr] = TEMP2_TO_REG_ADT7461(val);
else else
@@ -290,7 +291,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
data->temp11[nr] >> 8); data->temp11[nr] >> 8);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
data->temp11[nr] & 0xff); data->temp11[nr] & 0xff);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -311,11 +312,11 @@ static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
long hyst; long hyst;
down(&data->update_lock); mutex_lock(&data->update_lock);
hyst = TEMP1_FROM_REG(data->temp8[3]) - val; hyst = TEMP1_FROM_REG(data->temp8[3]) - val;
i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
HYST_TO_REG(hyst)); HYST_TO_REG(hyst));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -558,7 +559,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
data->kind = kind; data->kind = kind;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -646,7 +647,7 @@ static struct lm90_data *lm90_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm90_data *data = i2c_get_clientdata(client); struct lm90_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
u8 oldh, newh, l; u8 oldh, newh, l;
@@ -692,7 +693,7 @@ static struct lm90_data *lm90_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -46,6 +46,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* The LM92 and MAX6635 have 2 two-state pins for address selection, /* The LM92 and MAX6635 have 2 two-state pins for address selection,
resulting in 4 possible addresses. */ resulting in 4 possible addresses. */
@@ -96,7 +97,7 @@ static struct i2c_driver lm92_driver;
struct lm92_data { struct lm92_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -114,7 +115,7 @@ static struct lm92_data *lm92_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm92_data *data = i2c_get_clientdata(client); struct lm92_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) if (time_after(jiffies, data->last_updated + HZ)
|| !data->valid) { || !data->valid) {
@@ -134,7 +135,7 @@ static struct lm92_data *lm92_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }
@@ -158,10 +159,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
struct lm92_data *data = i2c_get_clientdata(client); \ struct lm92_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = TEMP_TO_REG(val); \ data->value = TEMP_TO_REG(val); \
i2c_smbus_write_word_data(client, reg, swab16(data->value)); \ i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
set_temp(temp1_crit, LM92_REG_TEMP_CRIT); set_temp(temp1_crit, LM92_REG_TEMP_CRIT);
@@ -194,11 +195,11 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute *
struct lm92_data *data = i2c_get_clientdata(client); struct lm92_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val; data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val;
i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST, i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
swab16(TEMP_TO_REG(data->temp1_hyst))); swab16(TEMP_TO_REG(data->temp1_hyst)));
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -348,7 +349,7 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields */ /* Fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the i2c subsystem a new client has arrived */ /* Tell the i2c subsystem a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))

View File

@@ -33,6 +33,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b, 0x29, 0x2a, 0x2b,
@@ -104,7 +105,7 @@ static struct i2c_driver max1619_driver = {
struct max1619_data { struct max1619_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -141,10 +142,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
struct max1619_data *data = i2c_get_clientdata(client); \ struct max1619_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \ long val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->value = TEMP_TO_REG(val); \ data->value = TEMP_TO_REG(val); \
i2c_smbus_write_byte_data(client, reg, data->value); \ i2c_smbus_write_byte_data(client, reg, data->value); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
@@ -262,7 +263,7 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */ /* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE); strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -330,7 +331,7 @@ static struct max1619_data *max1619_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct max1619_data *data = i2c_get_clientdata(client); struct max1619_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
dev_dbg(&client->dev, "Updating max1619 data.\n"); dev_dbg(&client->dev, "Updating max1619 data.\n");
@@ -353,7 +354,7 @@ static struct max1619_data *max1619_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -43,6 +43,7 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
static u8 devid; static u8 devid;
@@ -183,8 +184,8 @@ static inline u8 PWM_TO_REG(int val, int inv)
struct pc87360_data { struct pc87360_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -283,7 +284,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr,
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long fan_min = simple_strtol(buf, NULL, 10); long fan_min = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index])); fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index]));
/* If it wouldn't fit, change clock divisor */ /* If it wouldn't fit, change clock divisor */
@@ -300,23 +301,31 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr,
/* Write new divider, preserve alarm bits */ /* Write new divider, preserve alarm bits */
pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index), pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index),
data->fan_status[attr->index] & 0xF9); data->fan_status[attr->index] & 0xF9);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_and_set_fan(offset) \ static struct sensor_device_attribute fan_input[] = {
static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0),
show_fan_input, NULL, offset-1); \ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1),
static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2),
show_fan_min, set_fan_min, offset-1); \ };
static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ static struct sensor_device_attribute fan_status[] = {
show_fan_div, NULL, offset-1); \ SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0),
static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \ SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1),
show_fan_status, NULL, offset-1); SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2),
show_and_set_fan(1) };
show_and_set_fan(2) static struct sensor_device_attribute fan_div[] = {
show_and_set_fan(3) SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
};
static struct sensor_device_attribute fan_min[] = {
SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0),
SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1),
SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
};
static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
{ {
@@ -335,21 +344,20 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, con
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[attr->index] = PWM_TO_REG(val, data->pwm[attr->index] = PWM_TO_REG(val,
FAN_CONFIG_INVERT(data->fan_conf, attr->index)); FAN_CONFIG_INVERT(data->fan_conf, attr->index));
pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index), pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index),
data->pwm[attr->index]); data->pwm[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_and_set_pwm(offset) \ static struct sensor_device_attribute pwm[] = {
static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0),
show_pwm, set_pwm, offset-1); SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1),
show_and_set_pwm(1) SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
show_and_set_pwm(2) };
show_and_set_pwm(3)
static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
{ {
@@ -386,11 +394,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr,
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN, pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN,
data->in_min[attr->index]); data->in_min[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf, static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf,
@@ -401,35 +409,67 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr,
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[attr->index] = IN_TO_REG(val, data->in_max[attr->index] = IN_TO_REG(val,
data->in_vref); data->in_vref);
pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX, pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX,
data->in_max[attr->index]); data->in_max[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_and_set_in(offset) \ static struct sensor_device_attribute in_input[] = {
static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0),
show_in_input, NULL, offset); \ SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1),
static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2),
show_in_min, set_in_min, offset); \ SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3),
static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4),
show_in_max, set_in_max, offset); \ SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5),
static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \ SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6),
show_in_status, NULL, offset); SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7),
show_and_set_in(0) SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8),
show_and_set_in(1) SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9),
show_and_set_in(2) SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10),
show_and_set_in(3) };
show_and_set_in(4) static struct sensor_device_attribute in_status[] = {
show_and_set_in(5) SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0),
show_and_set_in(6) SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1),
show_and_set_in(7) SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2),
show_and_set_in(8) SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3),
show_and_set_in(9) SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4),
show_and_set_in(10) SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5),
SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6),
SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7),
SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8),
SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9),
SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10),
};
static struct sensor_device_attribute in_min[] = {
SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0),
SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1),
SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2),
SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3),
SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4),
SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5),
SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6),
SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7),
SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8),
SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9),
SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10),
};
static struct sensor_device_attribute in_max[] = {
SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0),
SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1),
SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2),
SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3),
SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4),
SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5),
SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6),
SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7),
SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8),
SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9),
SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
};
static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
{ {
@@ -473,11 +513,11 @@ static ssize_t set_therm_min(struct device *dev, struct device_attribute *devatt
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN, pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN,
data->in_min[attr->index]); data->in_min[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf, static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf,
@@ -488,11 +528,11 @@ static ssize_t set_therm_max(struct device *dev, struct device_attribute *devatt
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); data->in_max[attr->index] = IN_TO_REG(val, data->in_vref);
pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX, pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX,
data->in_max[attr->index]); data->in_max[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf, static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
@@ -503,28 +543,51 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref);
pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT, pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT,
data->in_crit[attr->index-11]); data->in_crit[attr->index-11]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_and_set_therm(offset) \ /* the +11 term below reflects the fact that VLM units 11,12,13 are
static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ used in the chip to measure voltage across the thermistors
show_therm_input, NULL, 11+offset-4); \ */
static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ static struct sensor_device_attribute therm_input[] = {
show_therm_min, set_therm_min, 11+offset-4); \ SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11),
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11),
show_therm_max, set_therm_max, 11+offset-4); \ SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11),
static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ };
show_therm_crit, set_therm_crit, 11+offset-4); \ static struct sensor_device_attribute therm_status[] = {
static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11),
show_therm_status, NULL, 11+offset-4); SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11),
show_and_set_therm(4) SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11),
show_and_set_therm(5) };
show_and_set_therm(6) static struct sensor_device_attribute therm_min[] = {
SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR,
show_therm_min, set_therm_min, 0+11),
SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR,
show_therm_min, set_therm_min, 1+11),
SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR,
show_therm_min, set_therm_min, 2+11),
};
static struct sensor_device_attribute therm_max[] = {
SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR,
show_therm_max, set_therm_max, 0+11),
SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR,
show_therm_max, set_therm_max, 1+11),
SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR,
show_therm_max, set_therm_max, 2+11),
};
static struct sensor_device_attribute therm_crit[] = {
SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR,
show_therm_crit, set_therm_crit, 0+11),
SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR,
show_therm_crit, set_therm_crit, 1+11),
SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR,
show_therm_crit, set_therm_crit, 2+11),
};
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)
{ {
@@ -592,11 +655,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_min[attr->index] = TEMP_TO_REG(val); data->temp_min[attr->index] = TEMP_TO_REG(val);
pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN, pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN,
data->temp_min[attr->index]); data->temp_min[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf, static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf,
@@ -607,11 +670,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[attr->index] = TEMP_TO_REG(val); data->temp_max[attr->index] = TEMP_TO_REG(val);
pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX, pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX,
data->temp_max[attr->index]); data->temp_max[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf, static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
@@ -622,28 +685,48 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devatt
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_crit[attr->index] = TEMP_TO_REG(val); data->temp_crit[attr->index] = TEMP_TO_REG(val);
pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT, pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT,
data->temp_crit[attr->index]); data->temp_crit[attr->index]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_and_set_temp(offset) \ static struct sensor_device_attribute temp_input[] = {
static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0),
show_temp_input, NULL, offset-1); \ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1),
static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2),
show_temp_min, set_temp_min, offset-1); \ };
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ static struct sensor_device_attribute temp_status[] = {
show_temp_max, set_temp_max, offset-1); \ SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0),
static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1),
show_temp_crit, set_temp_crit, offset-1); \ SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2),
static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ };
show_temp_status, NULL, offset-1); static struct sensor_device_attribute temp_min[] = {
show_and_set_temp(1) SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR,
show_and_set_temp(2) show_temp_min, set_temp_min, 0),
show_and_set_temp(3) SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR,
show_temp_min, set_temp_min, 1),
SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR,
show_temp_min, set_temp_min, 2),
};
static struct sensor_device_attribute temp_max[] = {
SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
show_temp_max, set_temp_max, 0),
SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
show_temp_max, set_temp_max, 1),
SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
show_temp_max, set_temp_max, 2),
};
static struct sensor_device_attribute temp_crit[] = {
SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
show_temp_crit, set_temp_crit, 0),
SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR,
show_temp_crit, set_temp_crit, 1),
SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR,
show_temp_crit, set_temp_crit, 2),
};
static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{ {
@@ -749,22 +832,24 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses
static int pc87360_detect(struct i2c_adapter *adapter) static int pc87360_detect(struct i2c_adapter *adapter)
{ {
int i; int i;
struct i2c_client *new_client; struct i2c_client *client;
struct pc87360_data *data; struct pc87360_data *data;
int err = 0; int err = 0;
const char *name = "pc87360"; const char *name = "pc87360";
int use_thermistors = 0; int use_thermistors = 0;
struct device *dev;
if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
new_client = &data->client; client = &data->client;
i2c_set_clientdata(new_client, data); dev = &client->dev;
new_client->addr = address; i2c_set_clientdata(client, data);
init_MUTEX(&data->lock); client->addr = address;
new_client->adapter = adapter; mutex_init(&data->lock);
new_client->driver = &pc87360_driver; client->adapter = adapter;
new_client->flags = 0; client->driver = &pc87360_driver;
client->flags = 0;
data->fannr = 2; data->fannr = 2;
data->innr = 0; data->innr = 0;
@@ -792,15 +877,15 @@ static int pc87360_detect(struct i2c_adapter *adapter)
break; break;
} }
strcpy(new_client->name, name); strlcpy(client->name, name, sizeof(client->name));
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (((data->address[i] = extra_isa[i])) if (((data->address[i] = extra_isa[i]))
&& !request_region(extra_isa[i], PC87360_EXTENT, && !request_region(extra_isa[i], PC87360_EXTENT,
pc87360_driver.driver.name)) { pc87360_driver.driver.name)) {
dev_err(&new_client->dev, "Region 0x%x-0x%x already " dev_err(&client->dev, "Region 0x%x-0x%x already "
"in use!\n", extra_isa[i], "in use!\n", extra_isa[i],
extra_isa[i]+PC87360_EXTENT-1); extra_isa[i]+PC87360_EXTENT-1);
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
@@ -814,7 +899,7 @@ static int pc87360_detect(struct i2c_adapter *adapter)
if (data->fannr) if (data->fannr)
data->fan_conf = confreg[0] | (confreg[1] << 8); data->fan_conf = confreg[0] | (confreg[1] << 8);
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(client)))
goto ERROR2; goto ERROR2;
/* Use the correct reference voltage /* Use the correct reference voltage
@@ -828,7 +913,7 @@ static int pc87360_detect(struct i2c_adapter *adapter)
PC87365_REG_TEMP_CONFIG); PC87365_REG_TEMP_CONFIG);
} }
data->in_vref = (i&0x02) ? 3025 : 2966; data->in_vref = (i&0x02) ? 3025 : 2966;
dev_dbg(&new_client->dev, "Using %s reference voltage\n", dev_dbg(&client->dev, "Using %s reference voltage\n",
(i&0x02) ? "external" : "internal"); (i&0x02) ? "external" : "internal");
data->vid_conf = confreg[3]; data->vid_conf = confreg[3];
@@ -847,154 +932,64 @@ static int pc87360_detect(struct i2c_adapter *adapter)
if (devid == 0xe9 && data->address[1]) /* PC87366 */ if (devid == 0xe9 && data->address[1]) /* PC87366 */
use_thermistors = confreg[2] & 0x40; use_thermistors = confreg[2] & 0x40;
pc87360_init_client(new_client, use_thermistors); pc87360_init_client(client, use_thermistors);
} }
/* Register sysfs hooks */ /* Register sysfs hooks */
data->class_dev = hwmon_device_register(&new_client->dev); data->class_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->class_dev)) { if (IS_ERR(data->class_dev)) {
err = PTR_ERR(data->class_dev); err = PTR_ERR(data->class_dev);
goto ERROR3; goto ERROR3;
} }
if (data->innr) { if (data->innr) {
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); for (i = 0; i < 11; i++) {
device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); device_create_file(dev, &in_input[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); device_create_file(dev, &in_min[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); device_create_file(dev, &in_max[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); device_create_file(dev, &in_status[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); }
device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); device_create_file(dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); device_create_file(dev, &dev_attr_vrm);
device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); device_create_file(dev, &dev_attr_alarms_in);
device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
device_create_file(&new_client->dev, &dev_attr_alarms_in);
} }
if (data->tempnr) { if (data->tempnr) {
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); for (i = 0; i < data->tempnr; i++) {
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr); device_create_file(dev, &temp_input[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr); device_create_file(dev, &temp_min[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr); device_create_file(dev, &temp_max[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); device_create_file(dev, &temp_crit[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr); device_create_file(dev, &temp_status[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); }
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr); device_create_file(dev, &dev_attr_alarms_temp);
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr); }
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms_temp);
}
if (data->tempnr == 3) {
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr);
}
if (data->innr == 14) { if (data->innr == 14) {
device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr); for (i = 0; i < 3; i++) {
device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr); device_create_file(dev, &therm_input[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr); device_create_file(dev, &therm_min[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr); device_create_file(dev, &therm_max[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr); device_create_file(dev, &therm_crit[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr); device_create_file(dev, &therm_status[i].dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr); }
device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr);
} }
if (data->fannr) { for (i = 0; i < data->fannr; i++) {
if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) { if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
device_create_file(&new_client->dev, device_create_file(dev, &fan_input[i].dev_attr);
&sensor_dev_attr_fan1_input.dev_attr); device_create_file(dev, &fan_min[i].dev_attr);
device_create_file(&new_client->dev, device_create_file(dev, &fan_div[i].dev_attr);
&sensor_dev_attr_fan1_min.dev_attr); device_create_file(dev, &fan_status[i].dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan1_div.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan1_status.dev_attr);
} }
if (FAN_CONFIG_CONTROL(data->fan_conf, i))
if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) { device_create_file(dev, &pwm[i].dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan2_input.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan2_min.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan2_div.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan2_status.dev_attr);
}
if (FAN_CONFIG_CONTROL(data->fan_conf, 0))
device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
if (FAN_CONFIG_CONTROL(data->fan_conf, 1))
device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
}
if (data->fannr == 3) {
if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) {
device_create_file(&new_client->dev,
&sensor_dev_attr_fan3_input.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan3_min.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan3_div.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan3_status.dev_attr);
}
if (FAN_CONFIG_CONTROL(data->fan_conf, 2))
device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
} }
return 0; return 0;
ERROR3: ERROR3:
i2c_detach_client(new_client); i2c_detach_client(client);
ERROR2: ERROR2:
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (data->address[i]) { if (data->address[i]) {
@@ -1033,11 +1028,11 @@ static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
{ {
int res; int res;
down(&(data->lock)); mutex_lock(&(data->lock));
if (bank != NO_BANK) if (bank != NO_BANK)
outb_p(bank, data->address[ldi] + PC87365_REG_BANK); outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
res = inb_p(data->address[ldi] + reg); res = inb_p(data->address[ldi] + reg);
up(&(data->lock)); mutex_unlock(&(data->lock));
return res; return res;
} }
@@ -1045,11 +1040,11 @@ static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
u8 reg, u8 value) u8 reg, u8 value)
{ {
down(&(data->lock)); mutex_lock(&(data->lock));
if (bank != NO_BANK) if (bank != NO_BANK)
outb_p(bank, data->address[ldi] + PC87365_REG_BANK); outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
outb_p(value, data->address[ldi] + reg); outb_p(value, data->address[ldi] + reg);
up(&(data->lock)); mutex_unlock(&(data->lock));
} }
static void pc87360_init_client(struct i2c_client *client, int use_thermistors) static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
@@ -1071,7 +1066,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
} }
nr = data->innr < 11 ? data->innr : 11; nr = data->innr < 11 ? data->innr : 11;
for (i=0; i<nr; i++) { for (i = 0; i < nr; i++) {
if (init >= init_in[i]) { if (init >= init_in[i]) {
/* Forcibly enable voltage channel */ /* Forcibly enable voltage channel */
reg = pc87360_read_value(data, LD_IN, i, reg = pc87360_read_value(data, LD_IN, i,
@@ -1088,14 +1083,14 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
/* We can't blindly trust the Super-I/O space configuration bit, /* We can't blindly trust the Super-I/O space configuration bit,
most BIOS won't set it properly */ most BIOS won't set it properly */
for (i=11; i<data->innr; i++) { for (i = 11; i < data->innr; i++) {
reg = pc87360_read_value(data, LD_IN, i, reg = pc87360_read_value(data, LD_IN, i,
PC87365_REG_TEMP_STATUS); PC87365_REG_TEMP_STATUS);
use_thermistors = use_thermistors || (reg & 0x01); use_thermistors = use_thermistors || (reg & 0x01);
} }
i = use_thermistors ? 2 : 0; i = use_thermistors ? 2 : 0;
for (; i<data->tempnr; i++) { for (; i < data->tempnr; i++) {
if (init >= init_temp[i]) { if (init >= init_temp[i]) {
/* Forcibly enable temperature channel */ /* Forcibly enable temperature channel */
reg = pc87360_read_value(data, LD_TEMP, i, reg = pc87360_read_value(data, LD_TEMP, i,
@@ -1111,7 +1106,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
} }
if (use_thermistors) { if (use_thermistors) {
for (i=11; i<data->innr; i++) { for (i = 11; i < data->innr; i++) {
if (init >= init_in[i]) { if (init >= init_in[i]) {
/* The pin may already be used by thermal /* The pin may already be used by thermal
diodes */ diodes */
@@ -1221,7 +1216,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
struct pc87360_data *data = i2c_get_clientdata(client); struct pc87360_data *data = i2c_get_clientdata(client);
u8 i; u8 i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
dev_dbg(&client->dev, "Data update\n"); dev_dbg(&client->dev, "Data update\n");
@@ -1321,7 +1316,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -60,6 +60,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
@@ -167,9 +168,9 @@ static inline u8 DIV_TO_REG(int val)
struct sis5595_data { struct sis5595_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
char maxins; /* == 3 if temp enabled, otherwise == 4 */ char maxins; /* == 3 if temp enabled, otherwise == 4 */
@@ -192,8 +193,8 @@ static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
static int sis5595_detect(struct i2c_adapter *adapter); static int sis5595_detect(struct i2c_adapter *adapter);
static int sis5595_detach_client(struct i2c_client *client); static int sis5595_detach_client(struct i2c_client *client);
static int sis5595_read_value(struct i2c_client *client, u8 register); static int sis5595_read_value(struct i2c_client *client, u8 reg);
static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value); static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value);
static struct sis5595_data *sis5595_update_device(struct device *dev); static struct sis5595_data *sis5595_update_device(struct device *dev);
static void sis5595_init_client(struct i2c_client *client); static void sis5595_init_client(struct i2c_client *client);
@@ -231,10 +232,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = IN_TO_REG(val); data->in_min[nr] = IN_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -245,10 +246,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = IN_TO_REG(val); data->in_max[nr] = IN_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -310,10 +311,10 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr,
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_over = TEMP_TO_REG(val); data->temp_over = TEMP_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over); sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -329,10 +330,10 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr,
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_hyst = TEMP_TO_REG(val); data->temp_hyst = TEMP_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst); sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -364,10 +365,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -390,7 +391,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
int reg; int reg;
down(&data->update_lock); mutex_lock(&data->update_lock);
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])); DIV_FROM_REG(data->fan_div[nr]));
reg = sis5595_read_value(client, SIS5595_REG_FANDIV); reg = sis5595_read_value(client, SIS5595_REG_FANDIV);
@@ -403,7 +404,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
default: default:
dev_err(&client->dev, "fan_div value %ld not " dev_err(&client->dev, "fan_div value %ld not "
"supported. Choose one of 1, 2, 4 or 8!\n", val); "supported. Choose one of 1, 2, 4 or 8!\n", val);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
@@ -419,7 +420,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
data->fan_min[nr] = data->fan_min[nr] =
FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -527,7 +528,7 @@ static int sis5595_detect(struct i2c_adapter *adapter)
new_client = &data->client; new_client = &data->client;
new_client->addr = address; new_client->addr = address;
init_MUTEX(&data->lock); mutex_init(&data->lock);
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->adapter = adapter; new_client->adapter = adapter;
new_client->driver = &sis5595_driver; new_client->driver = &sis5595_driver;
@@ -548,7 +549,7 @@ static int sis5595_detect(struct i2c_adapter *adapter)
strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE); strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -635,20 +636,20 @@ static int sis5595_read_value(struct i2c_client *client, u8 reg)
int res; int res;
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
down(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET); res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} }
static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value) static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
{ {
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
down(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET); outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET);
up(&data->lock); mutex_unlock(&data->lock);
return 0; return 0;
} }
@@ -667,7 +668,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -707,7 +708,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -35,6 +35,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
/* Address is autodetected, there is no default value */ /* Address is autodetected, there is no default value */
@@ -92,9 +93,9 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
struct smsc47b397_data { struct smsc47b397_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
struct semaphore update_lock; struct mutex update_lock;
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
int valid; int valid;
@@ -108,10 +109,10 @@ static int smsc47b397_read_value(struct i2c_client *client, u8 reg)
struct smsc47b397_data *data = i2c_get_clientdata(client); struct smsc47b397_data *data = i2c_get_clientdata(client);
int res; int res;
down(&data->lock); mutex_lock(&data->lock);
outb(reg, client->addr); outb(reg, client->addr);
res = inb_p(client->addr + 1); res = inb_p(client->addr + 1);
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} }
@@ -121,7 +122,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev)
struct smsc47b397_data *data = i2c_get_clientdata(client); struct smsc47b397_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
dev_dbg(&client->dev, "starting device update...\n"); dev_dbg(&client->dev, "starting device update...\n");
@@ -144,7 +145,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev)
dev_dbg(&client->dev, "... device update complete\n"); dev_dbg(&client->dev, "... device update complete\n");
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }
@@ -254,14 +255,14 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
new_client = &data->client; new_client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
init_MUTEX(&data->lock); mutex_init(&data->lock);
new_client->adapter = adapter; new_client->adapter = adapter;
new_client->driver = &smsc47b397_driver; new_client->driver = &smsc47b397_driver;
new_client->flags = 0; new_client->flags = 0;
strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE);
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
goto error_free; goto error_free;

View File

@@ -34,6 +34,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
/* Address is autodetected, there is no default value */ /* Address is autodetected, there is no default value */
@@ -102,9 +103,9 @@ superio_exit(void)
struct smsc47m1_data { struct smsc47m1_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
struct semaphore update_lock; struct mutex update_lock;
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
u8 fan[2]; /* Register value */ u8 fan[2]; /* Register value */
@@ -188,18 +189,18 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
struct smsc47m1_data *data = i2c_get_clientdata(client); struct smsc47m1_data *data = i2c_get_clientdata(client);
long rpmdiv, val = simple_strtol(buf, NULL, 10); long rpmdiv, val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]);
if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) { if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) {
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
data->fan_preload[nr]); data->fan_preload[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -220,14 +221,14 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
if (new_div == old_div) /* No change */ if (new_div == old_div) /* No change */
return count; return count;
down(&data->update_lock); mutex_lock(&data->update_lock);
switch (new_div) { switch (new_div) {
case 1: data->fan_div[nr] = 0; break; case 1: data->fan_div[nr] = 0; break;
case 2: data->fan_div[nr] = 1; break; case 2: data->fan_div[nr] = 1; break;
case 4: data->fan_div[nr] = 2; break; case 4: data->fan_div[nr] = 2; break;
case 8: data->fan_div[nr] = 3; break; case 8: data->fan_div[nr] = 3; break;
default: default:
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
@@ -241,7 +242,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
data->fan_preload[nr]); data->fan_preload[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -257,12 +258,12 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
if (val < 0 || val > 255) if (val < 0 || val > 255)
return -EINVAL; return -EINVAL;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[nr] &= 0x81; /* Preserve additional bits */ data->pwm[nr] &= 0x81; /* Preserve additional bits */
data->pwm[nr] |= PWM_TO_REG(val); data->pwm[nr] |= PWM_TO_REG(val);
smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
data->pwm[nr]); data->pwm[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -278,12 +279,12 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf,
if (val != 0 && val != 1) if (val != 0 && val != 1)
return -EINVAL; return -EINVAL;
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[nr] &= 0xFE; /* preserve the other bits */ data->pwm[nr] &= 0xFE; /* preserve the other bits */
data->pwm[nr] |= !val; data->pwm[nr] |= !val;
smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
data->pwm[nr]); data->pwm[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -408,13 +409,13 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
new_client = &data->client; new_client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
init_MUTEX(&data->lock); mutex_init(&data->lock);
new_client->adapter = adapter; new_client->adapter = adapter;
new_client->driver = &smsc47m1_driver; new_client->driver = &smsc47m1_driver;
new_client->flags = 0; new_client->flags = 0;
strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* If no function is properly configured, there's no point in /* If no function is properly configured, there's no point in
actually registering the chip. */ actually registering the chip. */
@@ -512,17 +513,17 @@ static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
{ {
int res; int res;
down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
res = inb_p(client->addr + reg); res = inb_p(client->addr + reg);
up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
return res; return res;
} }
static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
{ {
down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
outb_p(value, client->addr + reg); outb_p(value, client->addr + reg);
up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
} }
static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
@@ -531,7 +532,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct smsc47m1_data *data = i2c_get_clientdata(client); struct smsc47m1_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
int i; int i;
@@ -558,7 +559,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
data->last_updated = jiffies; data->last_updated = jiffies;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -39,6 +39,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
@@ -296,7 +297,7 @@ static inline long TEMP_FROM_REG10(u16 val)
struct via686a_data { struct via686a_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -355,11 +356,11 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = IN_TO_REG(val, nr); data->in_min[nr] = IN_TO_REG(val, nr);
via686a_write_value(client, VIA686A_REG_IN_MIN(nr), via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
data->in_min[nr]); data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_in_max(struct device *dev, const char *buf, static ssize_t set_in_max(struct device *dev, const char *buf,
@@ -368,11 +369,11 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = IN_TO_REG(val, nr); data->in_max[nr] = IN_TO_REG(val, nr);
via686a_write_value(client, VIA686A_REG_IN_MAX(nr), via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
data->in_max[nr]); data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_in_offset(offset) \ #define show_in_offset(offset) \
@@ -432,11 +433,11 @@ static ssize_t set_temp_over(struct device *dev, const char *buf,
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_over[nr] = TEMP_TO_REG(val); data->temp_over[nr] = TEMP_TO_REG(val);
via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr], via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr],
data->temp_over[nr]); data->temp_over[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_temp_hyst(struct device *dev, const char *buf, static ssize_t set_temp_hyst(struct device *dev, const char *buf,
@@ -445,11 +446,11 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf,
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_hyst[nr] = TEMP_TO_REG(val); data->temp_hyst[nr] = TEMP_TO_REG(val);
via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr], via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr],
data->temp_hyst[nr]); data->temp_hyst[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define show_temp_offset(offset) \ #define show_temp_offset(offset) \
@@ -508,10 +509,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_fan_div(struct device *dev, const char *buf, static ssize_t set_fan_div(struct device *dev, const char *buf,
@@ -521,12 +522,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
int old; int old;
down(&data->update_lock); mutex_lock(&data->update_lock);
old = via686a_read_value(client, VIA686A_REG_FANDIV); old = via686a_read_value(client, VIA686A_REG_FANDIV);
data->fan_div[nr] = DIV_TO_REG(val); data->fan_div[nr] = DIV_TO_REG(val);
old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
via686a_write_value(client, VIA686A_REG_FANDIV, old); via686a_write_value(client, VIA686A_REG_FANDIV, old);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -639,7 +640,7 @@ static int via686a_detect(struct i2c_adapter *adapter)
strlcpy(new_client->name, client_name, I2C_NAME_SIZE); strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
goto exit_free; goto exit_free;
@@ -733,7 +734,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -788,7 +789,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -35,6 +35,7 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
static int force_addr; static int force_addr;
@@ -148,7 +149,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
struct vt8231_data { struct vt8231_data {
struct i2c_client client; struct i2c_client client;
struct semaphore update_lock; struct mutex update_lock;
struct class_device *class_dev; struct class_device *class_dev;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -223,10 +224,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]); vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -239,10 +240,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]); vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -281,11 +282,11 @@ static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
0, 255); 0, 255);
vt8231_write_value(client, regvoltmin[5], data->in_min[5]); vt8231_write_value(client, regvoltmin[5], data->in_min[5]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -296,11 +297,11 @@ static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
0, 255); 0, 255);
vt8231_write_value(client, regvoltmax[5], data->in_max[5]); vt8231_write_value(client, regvoltmax[5], data->in_max[5]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -351,10 +352,10 @@ static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
vt8231_write_value(client, regtempmax[0], data->temp_max[0]); vt8231_write_value(client, regtempmax[0], data->temp_max[0]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
@@ -364,10 +365,10 @@ static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
vt8231_write_value(client, regtempmin[0], data->temp_min[0]); vt8231_write_value(client, regtempmin[0], data->temp_min[0]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -407,10 +408,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]); vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
@@ -422,10 +423,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10); int val = simple_strtol(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]); vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -520,10 +521,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
struct vt8231_data *data = i2c_get_clientdata(client); struct vt8231_data *data = i2c_get_clientdata(client);
int val = simple_strtoul(buf, NULL, 10); int val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -539,7 +540,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
long min = FAN_FROM_REG(data->fan_min[nr], long min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])); DIV_FROM_REG(data->fan_div[nr]));
down(&data->update_lock); mutex_lock(&data->update_lock);
switch (val) { switch (val) {
case 1: data->fan_div[nr] = 0; break; case 1: data->fan_div[nr] = 0; break;
case 2: data->fan_div[nr] = 1; break; case 2: data->fan_div[nr] = 1; break;
@@ -548,7 +549,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
default: default:
dev_err(&client->dev, "fan_div value %ld not supported." dev_err(&client->dev, "fan_div value %ld not supported."
"Choose one of 1, 2, 4 or 8!\n", val); "Choose one of 1, 2, 4 or 8!\n", val);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
@@ -558,7 +559,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
vt8231_write_value(client, VT8231_REG_FANDIV, old); vt8231_write_value(client, VT8231_REG_FANDIV, old);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -660,7 +661,7 @@ int vt8231_detect(struct i2c_adapter *adapter)
/* Fill in the remaining client fields and put into the global list */ /* Fill in the remaining client fields and put into the global list */
strlcpy(client->name, "vt8231", I2C_NAME_SIZE); strlcpy(client->name, "vt8231", I2C_NAME_SIZE);
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client))) if ((err = i2c_attach_client(client)))
@@ -745,7 +746,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
int i; int i;
u16 low; u16 low;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -804,7 +805,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -42,7 +42,9 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-isa.h> #include <linux/i2c-isa.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
#include "lm75.h" #include "lm75.h"
@@ -177,9 +179,9 @@ temp1_to_reg(int temp)
struct w83627ehf_data { struct w83627ehf_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -230,7 +232,7 @@ static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
struct w83627ehf_data *data = i2c_get_clientdata(client); struct w83627ehf_data *data = i2c_get_clientdata(client);
int res, word_sized = is_word_sized(reg); int res, word_sized = is_word_sized(reg);
down(&data->lock); mutex_lock(&data->lock);
w83627ehf_set_bank(client, reg); w83627ehf_set_bank(client, reg);
outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
@@ -242,7 +244,7 @@ static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
} }
w83627ehf_reset_bank(client, reg); w83627ehf_reset_bank(client, reg);
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} }
@@ -252,7 +254,7 @@ static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
struct w83627ehf_data *data = i2c_get_clientdata(client); struct w83627ehf_data *data = i2c_get_clientdata(client);
int word_sized = is_word_sized(reg); int word_sized = is_word_sized(reg);
down(&data->lock); mutex_lock(&data->lock);
w83627ehf_set_bank(client, reg); w83627ehf_set_bank(client, reg);
outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
@@ -264,7 +266,7 @@ static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
outb_p(value & 0xff, client->addr + DATA_REG_OFFSET); outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
w83627ehf_reset_bank(client, reg); w83627ehf_reset_bank(client, reg);
up(&data->lock); mutex_unlock(&data->lock);
return 0; return 0;
} }
@@ -322,7 +324,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
struct w83627ehf_data *data = i2c_get_clientdata(client); struct w83627ehf_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) if (time_after(jiffies, data->last_updated + HZ)
|| !data->valid) { || !data->valid) {
@@ -397,7 +399,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }
@@ -407,9 +409,12 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
#define show_fan_reg(reg) \ #define show_fan_reg(reg) \
static ssize_t \ static ssize_t \
show_##reg(struct device *dev, char *buf, int nr) \ show_##reg(struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \ { \
struct w83627ehf_data *data = w83627ehf_update_device(dev); \ struct w83627ehf_data *data = w83627ehf_update_device(dev); \
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
int nr = sensor_attr->index; \
return sprintf(buf, "%d\n", \ return sprintf(buf, "%d\n", \
fan_from_reg(data->reg[nr], \ fan_from_reg(data->reg[nr], \
div_from_reg(data->fan_div[nr]))); \ div_from_reg(data->fan_div[nr]))); \
@@ -418,23 +423,28 @@ show_fan_reg(fan);
show_fan_reg(fan_min); show_fan_reg(fan_min);
static ssize_t static ssize_t
show_fan_div(struct device *dev, char *buf, int nr) show_fan_div(struct device *dev, struct device_attribute *attr,
char *buf)
{ {
struct w83627ehf_data *data = w83627ehf_update_device(dev); struct w83627ehf_data *data = w83627ehf_update_device(dev);
return sprintf(buf, "%u\n", struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
div_from_reg(data->fan_div[nr])); int nr = sensor_attr->index;
return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
} }
static ssize_t static ssize_t
store_fan_min(struct device *dev, const char *buf, size_t count, int nr) store_fan_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct w83627ehf_data *data = i2c_get_clientdata(client); struct w83627ehf_data *data = i2c_get_clientdata(client);
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
unsigned int val = simple_strtoul(buf, NULL, 10); unsigned int val = simple_strtoul(buf, NULL, 10);
unsigned int reg; unsigned int reg;
u8 new_div; u8 new_div;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (!val) { if (!val) {
/* No min limit, alarm disabled */ /* No min limit, alarm disabled */
data->fan_min[nr] = 255; data->fan_min[nr] = 255;
@@ -482,63 +492,46 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
} }
w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr], w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
data->fan_min[nr]); data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
#define sysfs_fan_offset(offset) \ static struct sensor_device_attribute sda_fan_input[] = {
static ssize_t \ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
char *buf) \ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
{ \ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
return show_fan(dev, buf, offset-1); \ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
} \ };
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
show_reg_fan_##offset, NULL);
#define sysfs_fan_min_offset(offset) \ static struct sensor_device_attribute sda_fan_min[] = {
static ssize_t \ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ store_fan_min, 0),
char *buf) \ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
{ \ store_fan_min, 1),
return show_fan_min(dev, buf, offset-1); \ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
} \ store_fan_min, 2),
static ssize_t \ SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ store_fan_min, 3),
const char *buf, size_t count) \ SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
{ \ store_fan_min, 4),
return store_fan_min(dev, buf, count, offset-1); \ };
} \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_reg_fan##offset##_min, \
store_reg_fan##offset##_min);
#define sysfs_fan_div_offset(offset) \ static struct sensor_device_attribute sda_fan_div[] = {
static ssize_t \ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
char *buf) \ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
{ \ SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
return show_fan_div(dev, buf, offset - 1); \ SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
} \ };
static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
show_reg_fan##offset##_div, NULL);
sysfs_fan_offset(1); static void device_create_file_fan(struct device *dev, int i)
sysfs_fan_min_offset(1); {
sysfs_fan_div_offset(1); device_create_file(dev, &sda_fan_input[i].dev_attr);
sysfs_fan_offset(2); device_create_file(dev, &sda_fan_div[i].dev_attr);
sysfs_fan_min_offset(2); device_create_file(dev, &sda_fan_min[i].dev_attr);
sysfs_fan_div_offset(2); }
sysfs_fan_offset(3);
sysfs_fan_min_offset(3);
sysfs_fan_div_offset(3);
sysfs_fan_offset(4);
sysfs_fan_min_offset(4);
sysfs_fan_div_offset(4);
sysfs_fan_offset(5);
sysfs_fan_min_offset(5);
sysfs_fan_div_offset(5);
#define show_temp1_reg(reg) \ #define show_temp1_reg(reg) \
static ssize_t \ static ssize_t \
@@ -561,27 +554,24 @@ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
struct w83627ehf_data *data = i2c_get_clientdata(client); \ struct w83627ehf_data *data = i2c_get_clientdata(client); \
u32 val = simple_strtoul(buf, NULL, 10); \ u32 val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->temp1_##reg = temp1_to_reg(val); \ data->temp1_##reg = temp1_to_reg(val); \
w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
data->temp1_##reg); \ data->temp1_##reg); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
store_temp1_reg(OVER, max); store_temp1_reg(OVER, max);
store_temp1_reg(HYST, max_hyst); store_temp1_reg(HYST, max_hyst);
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL);
static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR,
show_temp1_max, store_temp1_max);
static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR,
show_temp1_max_hyst, store_temp1_max_hyst);
#define show_temp_reg(reg) \ #define show_temp_reg(reg) \
static ssize_t \ static ssize_t \
show_##reg (struct device *dev, char *buf, int nr) \ show_##reg(struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \ { \
struct w83627ehf_data *data = w83627ehf_update_device(dev); \ struct w83627ehf_data *data = w83627ehf_update_device(dev); \
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
int nr = sensor_attr->index; \
return sprintf(buf, "%d\n", \ return sprintf(buf, "%d\n", \
LM75_TEMP_FROM_REG(data->reg[nr])); \ LM75_TEMP_FROM_REG(data->reg[nr])); \
} }
@@ -591,55 +581,42 @@ show_temp_reg(temp_max_hyst);
#define store_temp_reg(REG, reg) \ #define store_temp_reg(REG, reg) \
static ssize_t \ static ssize_t \
store_##reg (struct device *dev, const char *buf, size_t count, int nr) \ store_##reg(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct w83627ehf_data *data = i2c_get_clientdata(client); \ struct w83627ehf_data *data = i2c_get_clientdata(client); \
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
int nr = sensor_attr->index; \
u32 val = simple_strtoul(buf, NULL, 10); \ u32 val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->reg[nr] = LM75_TEMP_TO_REG(val); \ data->reg[nr] = LM75_TEMP_TO_REG(val); \
w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \ w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
data->reg[nr]); \ data->reg[nr]); \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
store_temp_reg(OVER, temp_max); store_temp_reg(OVER, temp_max);
store_temp_reg(HYST, temp_max_hyst); store_temp_reg(HYST, temp_max_hyst);
#define sysfs_temp_offset(offset) \ static struct sensor_device_attribute sda_temp[] = {
static ssize_t \ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0),
show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0),
char *buf) \ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1),
{ \ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max,
return show_temp(dev, buf, offset - 2); \ store_temp1_max, 0),
} \ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ store_temp_max, 0),
show_reg_temp##offset, NULL); SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
store_temp_max, 1),
#define sysfs_temp_reg_offset(reg, offset) \ SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst,
static ssize_t \ store_temp1_max_hyst, 0),
show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
char *buf) \ store_temp_max_hyst, 0),
{ \ SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
return show_temp_##reg(dev, buf, offset - 2); \ store_temp_max_hyst, 1),
} \ };
static ssize_t \
store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_temp_##reg(dev, buf, count, offset - 2); \
} \
static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \
show_reg_temp##offset##_##reg, \
store_reg_temp##offset##_##reg);
sysfs_temp_offset(2);
sysfs_temp_reg_offset(max, 2);
sysfs_temp_reg_offset(max_hyst, 2);
sysfs_temp_offset(3);
sysfs_temp_reg_offset(max, 3);
sysfs_temp_reg_offset(max_hyst, 3);
/* /*
* Driver and client management * Driver and client management
@@ -673,6 +650,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
{ {
struct i2c_client *client; struct i2c_client *client;
struct w83627ehf_data *data; struct w83627ehf_data *data;
struct device *dev;
int i, err = 0; int i, err = 0;
if (!request_region(address + REGION_OFFSET, REGION_LENGTH, if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
@@ -689,14 +667,15 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
client = &data->client; client = &data->client;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
client->addr = address; client->addr = address;
init_MUTEX(&data->lock); mutex_init(&data->lock);
client->adapter = adapter; client->adapter = adapter;
client->driver = &w83627ehf_driver; client->driver = &w83627ehf_driver;
client->flags = 0; client->flags = 0;
dev = &client->dev;
strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the i2c layer a new client has arrived */ /* Tell the i2c layer a new client has arrived */
if ((err = i2c_attach_client(client))) if ((err = i2c_attach_client(client)))
@@ -720,42 +699,18 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
data->has_fan |= (1 << 4); data->has_fan |= (1 << 4);
/* Register sysfs hooks */ /* Register sysfs hooks */
data->class_dev = hwmon_device_register(&client->dev); data->class_dev = hwmon_device_register(dev);
if (IS_ERR(data->class_dev)) { if (IS_ERR(data->class_dev)) {
err = PTR_ERR(data->class_dev); err = PTR_ERR(data->class_dev);
goto exit_detach; goto exit_detach;
} }
device_create_file(&client->dev, &dev_attr_fan1_input); for (i = 0; i < 5; i++) {
device_create_file(&client->dev, &dev_attr_fan1_min); if (data->has_fan & (1 << i))
device_create_file(&client->dev, &dev_attr_fan1_div); device_create_file_fan(dev, i);
device_create_file(&client->dev, &dev_attr_fan2_input);
device_create_file(&client->dev, &dev_attr_fan2_min);
device_create_file(&client->dev, &dev_attr_fan2_div);
device_create_file(&client->dev, &dev_attr_fan3_input);
device_create_file(&client->dev, &dev_attr_fan3_min);
device_create_file(&client->dev, &dev_attr_fan3_div);
if (data->has_fan & (1 << 3)) {
device_create_file(&client->dev, &dev_attr_fan4_input);
device_create_file(&client->dev, &dev_attr_fan4_min);
device_create_file(&client->dev, &dev_attr_fan4_div);
} }
if (data->has_fan & (1 << 4)) { for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
device_create_file(&client->dev, &dev_attr_fan5_input); device_create_file(dev, &sda_temp[i].dev_attr);
device_create_file(&client->dev, &dev_attr_fan5_min);
device_create_file(&client->dev, &dev_attr_fan5_div);
}
device_create_file(&client->dev, &dev_attr_temp1_input);
device_create_file(&client->dev, &dev_attr_temp1_max);
device_create_file(&client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&client->dev, &dev_attr_temp2_input);
device_create_file(&client->dev, &dev_attr_temp2_max);
device_create_file(&client->dev, &dev_attr_temp2_max_hyst);
device_create_file(&client->dev, &dev_attr_temp3_input);
device_create_file(&client->dev, &dev_attr_temp3_max);
device_create_file(&client->dev, &dev_attr_temp3_max_hyst);
return 0; return 0;

View File

@@ -28,6 +28,7 @@
w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC)
w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC)
w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC)
w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC)
w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC)
For other winbond chips, and for i2c support in the above chips, For other winbond chips, and for i2c support in the above chips,
@@ -46,6 +47,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
#include "lm75.h" #include "lm75.h"
@@ -62,7 +64,7 @@ MODULE_PARM_DESC(force_i2c,
static unsigned short address; static unsigned short address;
/* Insmod parameters */ /* Insmod parameters */
enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
static int reset; static int reset;
module_param(reset, bool, 0); module_param(reset, bool, 0);
@@ -100,6 +102,10 @@ static int VAL; /* The value to read/write */
#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */
#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */
#define W83687THF_VID_EN 0x29 /* w83687thf only */
#define W83687THF_VID_CFG 0xF0 /* w83687thf only */
#define W83687THF_VID_DATA 0xF1 /* w83687thf only */
static inline void static inline void
superio_outb(int reg, int val) superio_outb(int reg, int val)
{ {
@@ -138,6 +144,7 @@ superio_exit(void)
#define W627THF_DEVID 0x82 #define W627THF_DEVID 0x82
#define W697_DEVID 0x60 #define W697_DEVID 0x60
#define W637_DEVID 0x70 #define W637_DEVID 0x70
#define W687THF_DEVID 0x85
#define WINB_ACT_REG 0x30 #define WINB_ACT_REG 0x30
#define WINB_BASE_REG 0x60 #define WINB_BASE_REG 0x60
/* Constants specified below */ /* Constants specified below */
@@ -201,11 +208,11 @@ superio_exit(void)
#define W83627HF_REG_PWM1 0x5A #define W83627HF_REG_PWM1 0x5A
#define W83627HF_REG_PWM2 0x5B #define W83627HF_REG_PWM2 0x5B
#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */ #define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */
#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */ #define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */
#define W83627THF_REG_PWM3 0x11 /* 637HF too */ #define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */
#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */ #define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF/687THF too */
static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
@@ -285,10 +292,10 @@ static inline u8 DIV_TO_REG(long val)
struct w83627hf_data { struct w83627hf_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -318,16 +325,15 @@ struct w83627hf_data {
Default = 3435. Default = 3435.
Other Betas unimplemented */ Other Betas unimplemented */
u8 vrm; u8 vrm;
u8 vrm_ovt; /* Register value, 627thf & 637hf only */ u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */
}; };
static int w83627hf_detect(struct i2c_adapter *adapter); static int w83627hf_detect(struct i2c_adapter *adapter);
static int w83627hf_detach_client(struct i2c_client *client); static int w83627hf_detach_client(struct i2c_client *client);
static int w83627hf_read_value(struct i2c_client *client, u16 register); static int w83627hf_read_value(struct i2c_client *client, u16 reg);
static int w83627hf_write_value(struct i2c_client *client, u16 register, static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value);
u16 value);
static struct w83627hf_data *w83627hf_update_device(struct device *dev); static struct w83627hf_data *w83627hf_update_device(struct device *dev);
static void w83627hf_init_client(struct i2c_client *client); static void w83627hf_init_client(struct i2c_client *client);
@@ -360,12 +366,12 @@ store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
\ \
val = simple_strtoul(buf, NULL, 10); \ val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->in_##reg[nr] = IN_TO_REG(val); \ data->in_##reg[nr] = IN_TO_REG(val); \
w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \
data->in_##reg[nr]); \ data->in_##reg[nr]); \
\ \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
store_in_reg(MIN, min) store_in_reg(MIN, min)
@@ -413,7 +419,8 @@ static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
long in0; long in0;
if ((data->vrm_ovt & 0x01) && if ((data->vrm_ovt & 0x01) &&
(w83627thf == data->type || w83637hf == data->type)) (w83627thf == data->type || w83637hf == data->type
|| w83687thf == data->type))
/* use VRM9 calculation */ /* use VRM9 calculation */
in0 = (long)((reg * 488 + 70000 + 50) / 100); in0 = (long)((reg * 488 + 70000 + 50) / 100);
@@ -451,10 +458,11 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if ((data->vrm_ovt & 0x01) && if ((data->vrm_ovt & 0x01) &&
(w83627thf == data->type || w83637hf == data->type)) (w83627thf == data->type || w83637hf == data->type
|| w83687thf == data->type))
/* use VRM9 calculation */ /* use VRM9 calculation */
data->in_min[0] = data->in_min[0] =
@@ -465,7 +473,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
data->in_min[0] = IN_TO_REG(val); data->in_min[0] = IN_TO_REG(val);
w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -478,10 +486,11 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if ((data->vrm_ovt & 0x01) && if ((data->vrm_ovt & 0x01) &&
(w83627thf == data->type || w83637hf == data->type)) (w83627thf == data->type || w83637hf == data->type
|| w83687thf == data->type))
/* use VRM9 calculation */ /* use VRM9 calculation */
data->in_max[0] = data->in_max[0] =
@@ -492,7 +501,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a
data->in_max[0] = IN_TO_REG(val); data->in_max[0] = IN_TO_REG(val);
w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -529,13 +538,13 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr - 1] = data->fan_min[nr - 1] =
FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr),
data->fan_min[nr - 1]); data->fan_min[nr - 1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -597,7 +606,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
\ \
val = simple_strtoul(buf, NULL, 10); \ val = simple_strtoul(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
\ \
if (nr >= 2) { /* TEMP2 and TEMP3 */ \ if (nr >= 2) { /* TEMP2 and TEMP3 */ \
data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
@@ -609,7 +618,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
data->temp_##reg); \ data->temp_##reg); \
} \ } \
\ \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
store_temp_reg(OVER, max); store_temp_reg(OVER, max);
@@ -718,7 +727,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
data->beep_mask = BEEP_MASK_TO_REG(val); data->beep_mask = BEEP_MASK_TO_REG(val);
@@ -736,7 +745,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, w83627hf_write_value(client, W83781D_REG_BEEP_INTS2,
val2 | data->beep_enable << 7); val2 | data->beep_enable << 7);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -783,7 +792,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
u8 reg; u8 reg;
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
/* Save fan_min */ /* Save fan_min */
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
@@ -805,7 +814,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -848,7 +857,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (data->type == w83627thf) { if (data->type == w83627thf) {
/* bits 0-3 are reserved in 627THF */ /* bits 0-3 are reserved in 627THF */
@@ -865,7 +874,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
data->pwm[nr - 1]); data->pwm[nr - 1]);
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -907,7 +916,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
switch (val) { switch (val) {
case 1: /* PII/Celeron diode */ case 1: /* PII/Celeron diode */
@@ -941,7 +950,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
break; break;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -980,7 +989,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr)
if(val != W627_DEVID && if(val != W627_DEVID &&
val != W627THF_DEVID && val != W627THF_DEVID &&
val != W697_DEVID && val != W697_DEVID &&
val != W637_DEVID) { val != W637_DEVID &&
val != W687THF_DEVID) {
superio_exit(); superio_exit();
return -ENODEV; return -ENODEV;
} }
@@ -1034,6 +1044,8 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
kind = w83627thf; kind = w83627thf;
else if(val == W637_DEVID) else if(val == W637_DEVID)
kind = w83637hf; kind = w83637hf;
else if (val == W687THF_DEVID)
kind = w83687thf;
else { else {
dev_info(&adapter->dev, dev_info(&adapter->dev,
"Unsupported chip (dev_id=0x%02X).\n", val); "Unsupported chip (dev_id=0x%02X).\n", val);
@@ -1057,7 +1069,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
new_client = &data->client; new_client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
init_MUTEX(&data->lock); mutex_init(&data->lock);
new_client->adapter = adapter; new_client->adapter = adapter;
new_client->driver = &w83627hf_driver; new_client->driver = &w83627hf_driver;
new_client->flags = 0; new_client->flags = 0;
@@ -1071,13 +1083,15 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
client_name = "w83697hf"; client_name = "w83697hf";
} else if (kind == w83637hf) { } else if (kind == w83637hf) {
client_name = "w83637hf"; client_name = "w83637hf";
} else if (kind == w83687thf) {
client_name = "w83687thf";
} }
/* Fill in the remaining client fields and put into the global list */ /* Fill in the remaining client fields and put into the global list */
strlcpy(new_client->name, client_name, I2C_NAME_SIZE); strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -1106,7 +1120,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
device_create_file_in(new_client, 2); device_create_file_in(new_client, 2);
device_create_file_in(new_client, 3); device_create_file_in(new_client, 3);
device_create_file_in(new_client, 4); device_create_file_in(new_client, 4);
if (kind != w83627thf && kind != w83637hf) { if (kind == w83627hf || kind == w83697hf) {
device_create_file_in(new_client, 5); device_create_file_in(new_client, 5);
device_create_file_in(new_client, 6); device_create_file_in(new_client, 6);
} }
@@ -1139,7 +1153,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
device_create_file_pwm(new_client, 1); device_create_file_pwm(new_client, 1);
device_create_file_pwm(new_client, 2); device_create_file_pwm(new_client, 2);
if (kind == w83627thf || kind == w83637hf) if (kind == w83627thf || kind == w83637hf || kind == w83687thf)
device_create_file_pwm(new_client, 3); device_create_file_pwm(new_client, 3);
device_create_file_sensor(new_client, 1); device_create_file_sensor(new_client, 1);
@@ -1187,7 +1201,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg)
struct w83627hf_data *data = i2c_get_clientdata(client); struct w83627hf_data *data = i2c_get_clientdata(client);
int res, word_sized; int res, word_sized;
down(&data->lock); mutex_lock(&data->lock);
word_sized = (((reg & 0xff00) == 0x100) word_sized = (((reg & 0xff00) == 0x100)
|| ((reg & 0xff00) == 0x200)) || ((reg & 0xff00) == 0x200))
&& (((reg & 0x00ff) == 0x50) && (((reg & 0x00ff) == 0x50)
@@ -1213,7 +1227,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg)
client->addr + W83781D_ADDR_REG_OFFSET); client->addr + W83781D_ADDR_REG_OFFSET);
outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
} }
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} }
@@ -1247,12 +1261,39 @@ exit:
return res; return res;
} }
static int w83687thf_read_vid(struct i2c_client *client)
{
int res = 0xff;
superio_enter();
superio_select(W83627HF_LD_HWM);
/* Make sure these GPIO pins are enabled */
if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) {
dev_dbg(&client->dev, "VID disabled, no VID function\n");
goto exit;
}
/* Make sure the pins are configured for input */
if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) {
dev_dbg(&client->dev, "VID configured as output, "
"no VID function\n");
goto exit;
}
res = superio_inb(W83687THF_VID_DATA) & 0x3f;
exit:
superio_exit();
return res;
}
static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
{ {
struct w83627hf_data *data = i2c_get_clientdata(client); struct w83627hf_data *data = i2c_get_clientdata(client);
int word_sized; int word_sized;
down(&data->lock); mutex_lock(&data->lock);
word_sized = (((reg & 0xff00) == 0x100) word_sized = (((reg & 0xff00) == 0x100)
|| ((reg & 0xff00) == 0x200)) || ((reg & 0xff00) == 0x200))
&& (((reg & 0x00ff) == 0x53) && (((reg & 0x00ff) == 0x53)
@@ -1277,7 +1318,7 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
client->addr + W83781D_ADDR_REG_OFFSET); client->addr + W83781D_ADDR_REG_OFFSET);
outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
} }
up(&data->lock); mutex_unlock(&data->lock);
return 0; return 0;
} }
@@ -1324,10 +1365,13 @@ static void w83627hf_init_client(struct i2c_client *client)
data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
} else if (w83627thf == data->type) { } else if (w83627thf == data->type) {
data->vid = w83627thf_read_gpio5(client); data->vid = w83627thf_read_gpio5(client);
} else if (w83687thf == data->type) {
data->vid = w83687thf_read_vid(client);
} }
/* Read VRM & OVT Config only once */ /* Read VRM & OVT Config only once */
if (w83627thf == data->type || w83637hf == data->type) { if (w83627thf == data->type || w83637hf == data->type
|| w83687thf == data->type) {
data->vrm_ovt = data->vrm_ovt =
w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
} }
@@ -1387,14 +1431,14 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
struct w83627hf_data *data = i2c_get_clientdata(client); struct w83627hf_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
for (i = 0; i <= 8; i++) { for (i = 0; i <= 8; i++) {
/* skip missing sensors */ /* skip missing sensors */
if (((data->type == w83697hf) && (i == 1)) || if (((data->type == w83697hf) && (i == 1)) ||
((data->type == w83627thf || data->type == w83637hf) ((data->type != w83627hf && data->type != w83697hf)
&& (i == 5 || i == 6))) && (i == 5 || i == 6)))
continue; continue;
data->in[i] = data->in[i] =
@@ -1470,7 +1514,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -42,6 +42,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
#include "lm75.h" #include "lm75.h"
@@ -56,6 +57,10 @@ I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}"); "{bus, clientaddr, subclientaddr1, subclientaddr2}");
static int reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
static int init = 1; static int init = 1;
module_param(init, bool, 0); module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
@@ -226,10 +231,10 @@ DIV_TO_REG(long val, enum chips type)
struct w83781d_data { struct w83781d_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore lock; struct mutex lock;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -267,9 +272,8 @@ static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter);
static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
static int w83781d_detach_client(struct i2c_client *client); static int w83781d_detach_client(struct i2c_client *client);
static int w83781d_read_value(struct i2c_client *client, u16 register); static int w83781d_read_value(struct i2c_client *client, u16 reg);
static int w83781d_write_value(struct i2c_client *client, u16 register, static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value);
u16 value);
static struct w83781d_data *w83781d_update_device(struct device *dev); static struct w83781d_data *w83781d_update_device(struct device *dev);
static void w83781d_init_client(struct i2c_client *client); static void w83781d_init_client(struct i2c_client *client);
@@ -311,11 +315,11 @@ static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count
\ \
val = simple_strtoul(buf, NULL, 10) / 10; \ val = simple_strtoul(buf, NULL, 10) / 10; \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
data->in_##reg[nr] = IN_TO_REG(val); \ data->in_##reg[nr] = IN_TO_REG(val); \
w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
\ \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
store_in_reg(MIN, min); store_in_reg(MIN, min);
@@ -381,13 +385,13 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr - 1] = data->fan_min[nr - 1] =
FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), w83781d_write_value(client, W83781D_REG_FAN_MIN(nr),
data->fan_min[nr - 1]); data->fan_min[nr - 1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -446,7 +450,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
\ \
val = simple_strtol(buf, NULL, 10); \ val = simple_strtol(buf, NULL, 10); \
\ \
down(&data->update_lock); \ mutex_lock(&data->update_lock); \
\ \
if (nr >= 2) { /* TEMP2 and TEMP3 */ \ if (nr >= 2) { /* TEMP2 and TEMP3 */ \
data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
@@ -458,7 +462,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
data->temp_##reg); \ data->temp_##reg); \
} \ } \
\ \
up(&data->update_lock); \ mutex_unlock(&data->update_lock); \
return count; \ return count; \
} }
store_temp_reg(OVER, max); store_temp_reg(OVER, max);
@@ -571,7 +575,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
data->beep_mask = BEEP_MASK_TO_REG(val, data->type); data->beep_mask = BEEP_MASK_TO_REG(val, data->type);
@@ -592,7 +596,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
w83781d_write_value(client, W83781D_REG_BEEP_INTS2, w83781d_write_value(client, W83781D_REG_BEEP_INTS2,
val2 | data->beep_enable << 7); val2 | data->beep_enable << 7);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -637,7 +641,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
u8 reg; u8 reg;
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
/* Save fan_min */ /* Save fan_min */
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
@@ -662,7 +666,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -709,10 +713,10 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[nr - 1] = PWM_TO_REG(val); data->pwm[nr - 1] = PWM_TO_REG(val);
w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -725,7 +729,7 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
switch (val) { switch (val) {
case 0: case 0:
@@ -742,11 +746,11 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
break; break;
default: default:
up(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -808,7 +812,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
switch (val) { switch (val) {
case 1: /* PII/Celeron diode */ case 1: /* PII/Celeron diode */
@@ -841,7 +845,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
break; break;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -1073,7 +1077,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
new_client = &data->client; new_client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
init_MUTEX(&data->lock); mutex_init(&data->lock);
new_client->adapter = adapter; new_client->adapter = adapter;
new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
new_client->flags = 0; new_client->flags = 0;
@@ -1178,7 +1182,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -1325,7 +1329,7 @@ w83781d_read_value(struct i2c_client *client, u16 reg)
int res, word_sized, bank; int res, word_sized, bank;
struct i2c_client *cl; struct i2c_client *cl;
down(&data->lock); mutex_lock(&data->lock);
if (i2c_is_isa_client(client)) { if (i2c_is_isa_client(client)) {
word_sized = (((reg & 0xff00) == 0x100) word_sized = (((reg & 0xff00) == 0x100)
|| ((reg & 0xff00) == 0x200)) || ((reg & 0xff00) == 0x200))
@@ -1383,7 +1387,7 @@ w83781d_read_value(struct i2c_client *client, u16 reg)
if (bank > 2) if (bank > 2)
i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
} }
up(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} }
@@ -1394,7 +1398,7 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
int word_sized, bank; int word_sized, bank;
struct i2c_client *cl; struct i2c_client *cl;
down(&data->lock); mutex_lock(&data->lock);
if (i2c_is_isa_client(client)) { if (i2c_is_isa_client(client)) {
word_sized = (((reg & 0xff00) == 0x100) word_sized = (((reg & 0xff00) == 0x100)
|| ((reg & 0xff00) == 0x200)) || ((reg & 0xff00) == 0x200))
@@ -1447,7 +1451,7 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
if (bank > 2) if (bank > 2)
i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
} }
up(&data->lock); mutex_unlock(&data->lock);
return 0; return 0;
} }
@@ -1459,8 +1463,17 @@ w83781d_init_client(struct i2c_client *client)
int type = data->type; int type = data->type;
u8 tmp; u8 tmp;
if (init && type != as99127f) { /* this resets registers we don't have if (reset && type != as99127f) { /* this resets registers we don't have
documentation for on the as99127f */ documentation for on the as99127f */
/* Resetting the chip has been the default for a long time,
but it causes the BIOS initializations (fan clock dividers,
thermal sensor types...) to be lost, so it is now optional.
It might even go away if nobody reports it as being useful,
as I see very little reason why this would be needed at
all. */
dev_info(&client->dev, "If reset=1 solved a problem you were "
"having, please report!\n");
/* save these registers */ /* save these registers */
i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
p = w83781d_read_value(client, W83781D_REG_PWMCLK12); p = w83781d_read_value(client, W83781D_REG_PWMCLK12);
@@ -1477,6 +1490,13 @@ w83781d_init_client(struct i2c_client *client)
w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
} }
/* Disable power-on abnormal beep, as advised by the datasheet.
Already done if reset=1. */
if (init && !reset && type != as99127f) {
i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
}
data->vrm = vid_which_vrm(); data->vrm = vid_which_vrm();
if ((type != w83781d) && (type != as99127f)) { if ((type != w83781d) && (type != as99127f)) {
@@ -1533,7 +1553,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
struct w83781d_data *data = i2c_get_clientdata(client); struct w83781d_data *data = i2c_get_clientdata(client);
int i; int i;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) { || !data->valid) {
@@ -1641,7 +1661,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -43,6 +43,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
@@ -271,7 +272,7 @@ struct w83792d_data {
struct class_device *class_dev; struct class_device *class_dev;
enum chips type; enum chips type;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
@@ -382,30 +383,40 @@ static ssize_t store_in_##reg (struct device *dev, \
store_in_reg(MIN, min); store_in_reg(MIN, min);
store_in_reg(MAX, max); store_in_reg(MAX, max);
#define sysfs_in_reg(offset) \ static struct sensor_device_attribute sda_in_input[] = {
static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
NULL, offset); \ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
show_in_min, store_in_min, offset); \ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
show_in_max, store_in_max, offset); SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
};
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),
SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
};
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),
SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
};
sysfs_in_reg(0);
sysfs_in_reg(1);
sysfs_in_reg(2);
sysfs_in_reg(3);
sysfs_in_reg(4);
sysfs_in_reg(5);
sysfs_in_reg(6);
sysfs_in_reg(7);
sysfs_in_reg(8);
#define device_create_file_in(client, offset) \
do { \
device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \
device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \
device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \
} while (0)
#define show_fan_reg(reg) \ #define show_fan_reg(reg) \
static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
@@ -486,28 +497,33 @@ store_fan_div(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_fan(offset) \ static struct sensor_device_attribute sda_fan_input[] = {
static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1),
offset); \ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2),
static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3),
show_fan_div, store_fan_div, offset); \ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4),
static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5),
show_fan_min, store_fan_min, offset); SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6),
SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7),
sysfs_fan(1); };
sysfs_fan(2); static struct sensor_device_attribute sda_fan_min[] = {
sysfs_fan(3); SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1),
sysfs_fan(4); SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2),
sysfs_fan(5); SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3),
sysfs_fan(6); SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4),
sysfs_fan(7); SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5),
SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6),
#define device_create_file_fan(client, offset) \ SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7),
do { \ };
device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \ static struct sensor_device_attribute sda_fan_div[] = {
device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \ SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1),
device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \ SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2),
} while (0) SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3),
SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4),
SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5),
SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6),
SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7),
};
/* read/write the temperature1, includes measured value and limits */ /* read/write the temperature1, includes measured value and limits */
@@ -539,21 +555,6 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1,
store_temp1, 1);
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1,
store_temp1, 2);
#define device_create_file_temp1(client) \
do { \
device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \
device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \
device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \
} while (0)
/* read/write the temperature2-3, includes measured value and limits */ /* read/write the temperature2-3, includes measured value and limits */
static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, static ssize_t show_temp23(struct device *dev, struct device_attribute *attr,
@@ -590,25 +591,23 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_temp23(name,idx) \ static struct sensor_device_attribute_2 sda_temp_input[] = {
static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \ SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0),
idx, 0); \ SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0),
static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),
show_temp23, store_temp23, idx, 2); \ };
static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \
show_temp23, store_temp23, idx, 4);
sysfs_temp23(temp2,0) static struct sensor_device_attribute_2 sda_temp_max[] = {
sysfs_temp23(temp3,1) SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1),
SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2),
#define device_create_file_temp_add(client, offset) \ SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2),
do { \ };
device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \
device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \
device_create_file(&client->dev, \
&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \
} while (0)
static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2),
SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 4),
SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4),
};
/* get reatime status of all sensors items: voltage, temp, fan */ /* get reatime status of all sensors items: voltage, temp, fan */
static ssize_t static ssize_t
@@ -620,10 +619,6 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
static static
DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
#define device_create_file_alarms(client) \
device_create_file(&client->dev, &dev_attr_alarms);
static ssize_t static ssize_t
show_pwm(struct device *dev, struct device_attribute *attr, show_pwm(struct device *dev, struct device_attribute *attr,
@@ -711,26 +706,19 @@ store_pwmenable(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_pwm(offset) \ static struct sensor_device_attribute sda_pwm[] = {
static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
show_pwm, store_pwm, offset); \ SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
show_pwmenable, store_pwmenable, offset); \ };
static struct sensor_device_attribute sda_pwm_enable[] = {
sysfs_pwm(1); SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
sysfs_pwm(2); show_pwmenable, store_pwmenable, 1),
sysfs_pwm(3); SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
show_pwmenable, store_pwmenable, 2),
SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
#define device_create_file_pwm(client, offset) \ show_pwmenable, store_pwmenable, 3),
do { \ };
device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \
} while (0)
#define device_create_file_pwmenable(client, offset) \
do { \
device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \
} while (0)
static ssize_t static ssize_t
@@ -764,18 +752,14 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_pwm_mode(offset) \ static struct sensor_device_attribute sda_pwm_mode[] = {
static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
show_pwm_mode, store_pwm_mode, offset); show_pwm_mode, store_pwm_mode, 1),
SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO,
sysfs_pwm_mode(1); show_pwm_mode, store_pwm_mode, 2),
sysfs_pwm_mode(2); SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO,
sysfs_pwm_mode(3); show_pwm_mode, store_pwm_mode, 3),
};
#define device_create_file_pwm_mode(client, offset) \
do { \
device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \
} while (0)
static ssize_t static ssize_t
@@ -788,12 +772,6 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
#define device_create_file_chassis(client) \
do { \
device_create_file(&client->dev, &dev_attr_chassis); \
} while (0)
static ssize_t static ssize_t
show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
{ {
@@ -824,13 +802,6 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
show_chassis_clear, store_chassis_clear); show_chassis_clear, store_chassis_clear);
#define device_create_file_chassis_clear(client) \
do { \
device_create_file(&client->dev, &dev_attr_chassis_clear); \
} while (0)
/* For Smart Fan I / Thermal Cruise */ /* For Smart Fan I / Thermal Cruise */
static ssize_t static ssize_t
show_thermal_cruise(struct device *dev, struct device_attribute *attr, show_thermal_cruise(struct device *dev, struct device_attribute *attr,
@@ -864,20 +835,14 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_thermal_cruise(offset) \ static struct sensor_device_attribute sda_thermal_cruise[] = {
static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO,
show_thermal_cruise, store_thermal_cruise, offset); show_thermal_cruise, store_thermal_cruise, 1),
SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO,
sysfs_thermal_cruise(1); show_thermal_cruise, store_thermal_cruise, 2),
sysfs_thermal_cruise(2); SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO,
sysfs_thermal_cruise(3); show_thermal_cruise, store_thermal_cruise, 3),
};
#define device_create_file_thermal_cruise(client, offset) \
do { \
device_create_file(&client->dev, \
&sensor_dev_attr_thermal_cruise##offset.dev_attr); \
} while (0)
/* For Smart Fan I/Thermal Cruise and Smart Fan II */ /* For Smart Fan I/Thermal Cruise and Smart Fan II */
static ssize_t static ssize_t
@@ -916,19 +881,14 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_tolerance(offset) \ static struct sensor_device_attribute sda_tolerance[] = {
static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \ SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO,
show_tolerance, store_tolerance, offset); show_tolerance, store_tolerance, 1),
SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO,
sysfs_tolerance(1); show_tolerance, store_tolerance, 2),
sysfs_tolerance(2); SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO,
sysfs_tolerance(3); show_tolerance, store_tolerance, 3),
};
#define device_create_file_tolerance(client, offset) \
do { \
device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \
} while (0)
/* For Smart Fan II */ /* For Smart Fan II */
static ssize_t static ssize_t
@@ -964,28 +924,34 @@ store_sf2_point(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_sf2_point(offset, index) \ static struct sensor_device_attribute_2 sda_sf2_point[] = {
static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \ SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR,
show_sf2_point, store_sf2_point, offset, index); show_sf2_point, store_sf2_point, 1, 1),
SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR,
show_sf2_point, store_sf2_point, 2, 1),
SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR,
show_sf2_point, store_sf2_point, 3, 1),
SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR,
show_sf2_point, store_sf2_point, 4, 1),
sysfs_sf2_point(1, 1); /* Fan1 */ SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR,
sysfs_sf2_point(2, 1); /* Fan1 */ show_sf2_point, store_sf2_point, 1, 2),
sysfs_sf2_point(3, 1); /* Fan1 */ SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR,
sysfs_sf2_point(4, 1); /* Fan1 */ show_sf2_point, store_sf2_point, 2, 2),
sysfs_sf2_point(1, 2); /* Fan2 */ SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR,
sysfs_sf2_point(2, 2); /* Fan2 */ show_sf2_point, store_sf2_point, 3, 2),
sysfs_sf2_point(3, 2); /* Fan2 */ SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR,
sysfs_sf2_point(4, 2); /* Fan2 */ show_sf2_point, store_sf2_point, 4, 2),
sysfs_sf2_point(1, 3); /* Fan3 */
sysfs_sf2_point(2, 3); /* Fan3 */
sysfs_sf2_point(3, 3); /* Fan3 */
sysfs_sf2_point(4, 3); /* Fan3 */
#define device_create_file_sf2_point(client, offset, index) \ SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR,
do { \ show_sf2_point, store_sf2_point, 1, 3),
device_create_file(&client->dev, \ SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR,
&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \ show_sf2_point, store_sf2_point, 2, 3),
} while (0) SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR,
show_sf2_point, store_sf2_point, 3, 3),
SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR,
show_sf2_point, store_sf2_point, 4, 3),
};
static ssize_t static ssize_t
@@ -1026,26 +992,28 @@ store_sf2_level(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define sysfs_sf2_level(offset, index) \ static struct sensor_device_attribute_2 sda_sf2_level[] = {
static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \ SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR,
show_sf2_level, store_sf2_level, offset, index); show_sf2_level, store_sf2_level, 1, 1),
SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR,
show_sf2_level, store_sf2_level, 2, 1),
SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR,
show_sf2_level, store_sf2_level, 3, 1),
sysfs_sf2_level(1, 1); /* Fan1 */ SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR,
sysfs_sf2_level(2, 1); /* Fan1 */ show_sf2_level, store_sf2_level, 1, 2),
sysfs_sf2_level(3, 1); /* Fan1 */ SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR,
sysfs_sf2_level(1, 2); /* Fan2 */ show_sf2_level, store_sf2_level, 2, 2),
sysfs_sf2_level(2, 2); /* Fan2 */ SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR,
sysfs_sf2_level(3, 2); /* Fan2 */ show_sf2_level, store_sf2_level, 3, 2),
sysfs_sf2_level(1, 3); /* Fan3 */
sysfs_sf2_level(2, 3); /* Fan3 */
sysfs_sf2_level(3, 3); /* Fan3 */
#define device_create_file_sf2_level(client, offset, index) \
do { \
device_create_file(&client->dev, \
&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \
} while (0)
SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR,
show_sf2_level, store_sf2_level, 1, 3),
SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR,
show_sf2_level, store_sf2_level, 2, 3),
SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR,
show_sf2_level, store_sf2_level, 3, 3),
};
/* This function is called when: /* This function is called when:
* w83792d_driver is inserted (when this module is loaded), for each * w83792d_driver is inserted (when this module is loaded), for each
@@ -1147,12 +1115,19 @@ ERROR_SC_0:
return err; return err;
} }
static void device_create_file_fan(struct device *dev, int i)
{
device_create_file(dev, &sda_fan_input[i].dev_attr);
device_create_file(dev, &sda_fan_div[i].dev_attr);
device_create_file(dev, &sda_fan_min[i].dev_attr);
}
static int static int
w83792d_detect(struct i2c_adapter *adapter, int address, int kind) w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
int i = 0, val1 = 0, val2; int i = 0, val1 = 0, val2;
struct i2c_client *new_client; struct i2c_client *client;
struct device *dev;
struct w83792d_data *data; struct w83792d_data *data;
int err = 0; int err = 0;
const char *client_name = ""; const char *client_name = "";
@@ -1170,12 +1145,13 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR0; goto ERROR0;
} }
new_client = &data->client; client = &data->client;
i2c_set_clientdata(new_client, data); dev = &client->dev;
new_client->addr = address; i2c_set_clientdata(client, data);
new_client->adapter = adapter; client->addr = address;
new_client->driver = &w83792d_driver; client->adapter = adapter;
new_client->flags = 0; client->driver = &w83792d_driver;
client->flags = 0;
/* Now, we do the remaining detection. */ /* Now, we do the remaining detection. */
@@ -1184,13 +1160,12 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
force_*=... parameter, and the Winbond will be reset to the right force_*=... parameter, and the Winbond will be reset to the right
bank. */ bank. */
if (kind < 0) { if (kind < 0) {
if (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) { if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) {
dev_warn(&new_client->dev, "Detection failed at step " dev_warn(dev, "Detection failed at step 3\n");
"3\n");
goto ERROR1; goto ERROR1;
} }
val1 = w83792d_read_value(new_client, W83792D_REG_BANK); val1 = w83792d_read_value(client, W83792D_REG_BANK);
val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
/* Check for Winbond ID if in bank 0 */ /* Check for Winbond ID if in bank 0 */
if (!(val1 & 0x07)) { /* is Bank0 */ if (!(val1 & 0x07)) { /* is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) || if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
@@ -1200,34 +1175,33 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
} }
/* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
should match */ should match */
if (w83792d_read_value(new_client, if (w83792d_read_value(client,
W83792D_REG_I2C_ADDR) != address) { W83792D_REG_I2C_ADDR) != address) {
dev_warn(&new_client->dev, "Detection failed " dev_warn(dev, "Detection failed at step 5\n");
"at step 5\n");
goto ERROR1; goto ERROR1;
} }
} }
/* We have either had a force parameter, or we have already detected the /* We have either had a force parameter, or we have already detected the
Winbond. Put it now into bank 0 and Vendor ID High Byte */ Winbond. Put it now into bank 0 and Vendor ID High Byte */
w83792d_write_value(new_client, w83792d_write_value(client,
W83792D_REG_BANK, W83792D_REG_BANK,
(w83792d_read_value(new_client, (w83792d_read_value(client,
W83792D_REG_BANK) & 0x78) | 0x80); W83792D_REG_BANK) & 0x78) | 0x80);
/* Determine the chip type. */ /* Determine the chip type. */
if (kind <= 0) { if (kind <= 0) {
/* get vendor ID */ /* get vendor ID */
val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
if (val2 != 0x5c) { /* the vendor is NOT Winbond */ if (val2 != 0x5c) { /* the vendor is NOT Winbond */
goto ERROR1; goto ERROR1;
} }
val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID); val1 = w83792d_read_value(client, W83792D_REG_WCHIPID);
if (val1 == 0x7a) { if (val1 == 0x7a) {
kind = w83792d; kind = w83792d;
} else { } else {
if (kind == 0) if (kind == 0)
dev_warn(&new_client->dev, dev_warn(dev,
"w83792d: Ignoring 'force' parameter for" "w83792d: Ignoring 'force' parameter for"
" unknown chip at adapter %d, address" " unknown chip at adapter %d, address"
" 0x%02x\n", i2c_adapter_id(adapter), " 0x%02x\n", i2c_adapter_id(adapter),
@@ -1239,120 +1213,86 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == w83792d) { if (kind == w83792d) {
client_name = "w83792d"; client_name = "w83792d";
} else { } else {
dev_err(&new_client->dev, "w83792d: Internal error: unknown" dev_err(dev, "w83792d: Internal error: unknown"
" kind (%d)?!?", kind); " kind (%d)?!?", kind);
goto ERROR1; goto ERROR1;
} }
/* Fill in the remaining client fields and put into the global list */ /* Fill in the remaining client fields and put into the global list */
strlcpy(new_client->name, client_name, I2C_NAME_SIZE); strlcpy(client->name, client_name, I2C_NAME_SIZE);
data->type = kind; data->type = kind;
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(client)))
goto ERROR1; goto ERROR1;
if ((err = w83792d_detect_subclients(adapter, address, if ((err = w83792d_detect_subclients(adapter, address,
kind, new_client))) kind, client)))
goto ERROR2; goto ERROR2;
/* Initialize the chip */ /* Initialize the chip */
w83792d_init_client(new_client); w83792d_init_client(client);
/* A few vars need to be filled upon startup */ /* A few vars need to be filled upon startup */
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
data->fan_min[i] = w83792d_read_value(new_client, data->fan_min[i] = w83792d_read_value(client,
W83792D_REG_FAN_MIN[i]); W83792D_REG_FAN_MIN[i]);
} }
/* Register sysfs hooks */ /* Register sysfs hooks */
data->class_dev = hwmon_device_register(&new_client->dev); data->class_dev = hwmon_device_register(dev);
if (IS_ERR(data->class_dev)) { if (IS_ERR(data->class_dev)) {
err = PTR_ERR(data->class_dev); err = PTR_ERR(data->class_dev);
goto ERROR3; goto ERROR3;
} }
device_create_file_in(new_client, 0); for (i = 0; i < 9; i++) {
device_create_file_in(new_client, 1); device_create_file(dev, &sda_in_input[i].dev_attr);
device_create_file_in(new_client, 2); device_create_file(dev, &sda_in_max[i].dev_attr);
device_create_file_in(new_client, 3); device_create_file(dev, &sda_in_min[i].dev_attr);
device_create_file_in(new_client, 4); }
device_create_file_in(new_client, 5); for (i = 0; i < 3; i++)
device_create_file_in(new_client, 6); device_create_file_fan(dev, i);
device_create_file_in(new_client, 7);
device_create_file_in(new_client, 8);
device_create_file_fan(new_client, 1);
device_create_file_fan(new_client, 2);
device_create_file_fan(new_client, 3);
/* Read GPIO enable register to check if pins for fan 4,5 are used as /* Read GPIO enable register to check if pins for fan 4,5 are used as
GPIO */ GPIO */
val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN); val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN);
if (!(val1 & 0x40)) if (!(val1 & 0x40))
device_create_file_fan(new_client, 4); device_create_file_fan(dev, 3);
if (!(val1 & 0x20)) if (!(val1 & 0x20))
device_create_file_fan(new_client, 5); device_create_file_fan(dev, 4);
val1 = w83792d_read_value(new_client, W83792D_REG_PIN); val1 = w83792d_read_value(client, W83792D_REG_PIN);
if (val1 & 0x40) if (val1 & 0x40)
device_create_file_fan(new_client, 6); device_create_file_fan(dev, 5);
if (val1 & 0x04) if (val1 & 0x04)
device_create_file_fan(new_client, 7); device_create_file_fan(dev, 6);
device_create_file_temp1(new_client); /* Temp1 */ for (i = 0; i < 3; i++) {
device_create_file_temp_add(new_client, 2); /* Temp2 */ device_create_file(dev, &sda_temp_input[i].dev_attr);
device_create_file_temp_add(new_client, 3); /* Temp3 */ device_create_file(dev, &sda_temp_max[i].dev_attr);
device_create_file(dev, &sda_temp_max_hyst[i].dev_attr);
device_create_file(dev, &sda_thermal_cruise[i].dev_attr);
device_create_file(dev, &sda_tolerance[i].dev_attr);
}
device_create_file_alarms(new_client); for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) {
device_create_file(dev, &sda_pwm[i].dev_attr);
device_create_file(dev, &sda_pwm_enable[i].dev_attr);
device_create_file(dev, &sda_pwm_mode[i].dev_attr);
}
device_create_file_pwm(new_client, 1); device_create_file(dev, &dev_attr_alarms);
device_create_file_pwm(new_client, 2); device_create_file(dev, &dev_attr_chassis);
device_create_file_pwm(new_client, 3); device_create_file(dev, &dev_attr_chassis_clear);
device_create_file_pwmenable(new_client, 1); for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++)
device_create_file_pwmenable(new_client, 2); device_create_file(dev, &sda_sf2_point[i].dev_attr);
device_create_file_pwmenable(new_client, 3);
device_create_file_pwm_mode(new_client, 1); for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++)
device_create_file_pwm_mode(new_client, 2); device_create_file(dev, &sda_sf2_level[i].dev_attr);
device_create_file_pwm_mode(new_client, 3);
device_create_file_chassis(new_client);
device_create_file_chassis_clear(new_client);
device_create_file_thermal_cruise(new_client, 1);
device_create_file_thermal_cruise(new_client, 2);
device_create_file_thermal_cruise(new_client, 3);
device_create_file_tolerance(new_client, 1);
device_create_file_tolerance(new_client, 2);
device_create_file_tolerance(new_client, 3);
device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */
device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */
device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */
device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */
device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */
device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */
device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */
device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */
device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */
device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */
device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */
device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */
device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */
device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */
device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */
device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */
device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */
device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */
device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */
device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */
device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */
return 0; return 0;
@@ -1366,7 +1306,7 @@ ERROR3:
kfree(data->lm75[1]); kfree(data->lm75[1]);
} }
ERROR2: ERROR2:
i2c_detach_client(new_client); i2c_detach_client(client);
ERROR1: ERROR1:
kfree(data); kfree(data);
ERROR0: ERROR0:
@@ -1434,7 +1374,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
int i, j; int i, j;
u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after if (time_after
(jiffies - data->last_updated, (unsigned long) (HZ * 3)) (jiffies - data->last_updated, (unsigned long) (HZ * 3))
@@ -1545,7 +1485,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
#ifdef DEBUG #ifdef DEBUG
w83792d_print_debug(data, dev); w83792d_print_debug(data, dev);

View File

@@ -39,6 +39,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h>
/* How many retries on register read error */ /* How many retries on register read error */
#define MAX_RETRIES 5 #define MAX_RETRIES 5
@@ -107,7 +108,7 @@ static struct i2c_driver w83l785ts_driver = {
struct w83l785ts_data { struct w83l785ts_data {
struct i2c_client client; struct i2c_client client;
struct class_device *class_dev; struct class_device *class_dev;
struct semaphore update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
@@ -221,7 +222,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields. */ /* We can fill in the remaining client fields. */
strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE); strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Default values in case the first read fails (unlikely). */ /* Default values in case the first read fails (unlikely). */
data->temp[1] = data->temp[0] = 0; data->temp[1] = data->temp[0] = 0;
@@ -299,7 +300,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct w83l785ts_data *data = i2c_get_clientdata(client); struct w83l785ts_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) { if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) {
dev_dbg(&client->dev, "Updating w83l785ts data.\n"); dev_dbg(&client->dev, "Updating w83l785ts data.\n");
@@ -312,7 +313,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
up(&data->update_lock); mutex_unlock(&data->update_lock);
return data; return data;
} }

View File

@@ -168,12 +168,14 @@ config I2C_PIIX4
help help
If you say yes to this option, support will be included for the Intel If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following PIIX4 family of mainboard I2C interfaces. Specifically, the following
versions of the chipset are supported: versions of the chipset are supported (note that Serverworks is part
of Broadcom):
Intel PIIX4 Intel PIIX4
Intel 440MX Intel 440MX
Serverworks OSB4 Serverworks OSB4
Serverworks CSB5 Serverworks CSB5
Serverworks CSB6 Serverworks CSB6
Serverworks HT-1000
SMSC Victory66 SMSC Victory66
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
@@ -389,10 +391,11 @@ config SCx200_I2C_SDA
also be specified with a module parameter. also be specified with a module parameter.
config SCx200_ACB config SCx200_ACB
tristate "NatSemi SCx200 ACCESS.bus" tristate "Geode ACCESS.bus support"
depends on I2C && PCI depends on X86_32 && I2C && PCI
help help
Enable the use of the ACCESS.bus controllers of a SCx200 processor. Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
SC1100 processors and the CS5535 and CS5536 Geode companion devices.
If you don't know what to do here, say N. If you don't know what to do here, say N.

View File

@@ -63,7 +63,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/semaphore.h>
/* ALI1535 SMBus address offsets */ /* ALI1535 SMBus address offsets */
@@ -136,7 +135,6 @@
static struct pci_driver ali1535_driver; static struct pci_driver ali1535_driver;
static unsigned short ali1535_smba; static unsigned short ali1535_smba;
static DECLARE_MUTEX(i2c_ali1535_sem);
/* Detect whether a ALI1535 can be found, and initialize it, where necessary. /* Detect whether a ALI1535 can be found, and initialize it, where necessary.
Note the differences between kernels with the old PCI BIOS interface and Note the differences between kernels with the old PCI BIOS interface and
@@ -345,7 +343,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
int timeout; int timeout;
s32 result = 0; s32 result = 0;
down(&i2c_ali1535_sem);
/* make sure SMBus is idle */ /* make sure SMBus is idle */
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
for (timeout = 0; for (timeout = 0;
@@ -460,7 +457,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
break; break;
} }
EXIT: EXIT:
up(&i2c_ali1535_sem);
return result; return result;
} }

View File

@@ -38,6 +38,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mutex.h>
extern struct i2c_adapter amd756_smbus; extern struct i2c_adapter amd756_smbus;
@@ -45,7 +46,7 @@ static struct i2c_adapter *s4882_adapter;
static struct i2c_algorithm *s4882_algo; static struct i2c_algorithm *s4882_algo;
/* Wrapper access functions for multiplexed SMBus */ /* Wrapper access functions for multiplexed SMBus */
static struct semaphore amd756_lock; static DEFINE_MUTEX(amd756_lock);
static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
@@ -59,12 +60,12 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
|| addr == 0x18) || addr == 0x18)
return -1; return -1;
down(&amd756_lock); mutex_lock(&amd756_lock);
error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write,
command, size, data); command, size, data);
up(&amd756_lock); mutex_unlock(&amd756_lock);
return error; return error;
} }
@@ -87,7 +88,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
return -1; return -1;
down(&amd756_lock); mutex_lock(&amd756_lock);
if (last_channels != channels) { if (last_channels != channels) {
union i2c_smbus_data mplxdata; union i2c_smbus_data mplxdata;
@@ -105,7 +106,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
command, size, data); command, size, data);
UNLOCK: UNLOCK:
up(&amd756_lock); mutex_unlock(&amd756_lock);
return error; return error;
} }
@@ -166,8 +167,6 @@ static int __init amd756_s4882_init(void)
} }
printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n");
init_MUTEX(&amd756_lock);
/* Define the 5 virtual adapters and algorithms structures */ /* Define the 5 virtual adapters and algorithms structures */
if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter),
GFP_KERNEL))) { GFP_KERNEL))) {

View File

@@ -1,85 +0,0 @@
/*
* linux/drivers/i2c/i2c-frodo.c
*
* Author: Abraham van der Merwe <abraham@2d3d.co.za>
*
* An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110
* Development board (Frodo).
*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <asm/hardware.h>
static void frodo_setsda (void *data,int state)
{
if (state)
FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT;
else
FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT;
}
static void frodo_setscl (void *data,int state)
{
if (state)
FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT;
else
FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT;
}
static int frodo_getsda (void *data)
{
return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0);
}
static int frodo_getscl (void *data)
{
return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0);
}
static struct i2c_algo_bit_data bit_frodo_data = {
.setsda = frodo_setsda,
.setscl = frodo_setscl,
.getsda = frodo_getsda,
.getscl = frodo_getscl,
.udelay = 80,
.mdelay = 80,
.timeout = HZ
};
static struct i2c_adapter frodo_ops = {
.owner = THIS_MODULE,
.id = I2C_HW_B_FRODO,
.algo_data = &bit_frodo_data,
.dev = {
.name = "Frodo adapter driver",
},
};
static int __init i2c_frodo_init (void)
{
return i2c_bit_add_bus(&frodo_ops);
}
static void __exit i2c_frodo_exit (void)
{
i2c_bit_del_bus(&frodo_ops);
}
MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
MODULE_LICENSE ("GPL");
module_init (i2c_frodo_init);
module_exit (i2c_frodo_exit);

View File

@@ -125,7 +125,7 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
static int __init i2c_isa_init(void) static int __init i2c_isa_init(void)
{ {
init_MUTEX(&isa_adapter.clist_lock); mutex_init(&isa_adapter.clist_lock);
INIT_LIST_HEAD(&isa_adapter.clients); INIT_LIST_HEAD(&isa_adapter.clients);
isa_adapter.nr = ANY_I2C_ISA_BUS; isa_adapter.nr = ANY_I2C_ISA_BUS;

View File

@@ -200,9 +200,7 @@ static struct i2c_adapter iic_ite_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_I_IIC, .id = I2C_HW_I_IIC,
.algo_data = &iic_ite_data, .algo_data = &iic_ite_data,
.dev = { .name = "ITE IIC adapter",
.name = "ITE IIC adapter",
},
}; };
/* Called when the module is loaded. This function starts the /* Called when the module is loaded. This function starts the

View File

@@ -126,6 +126,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
drv_data->algo_data.timeout = 100; drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP4XX; drv_data->adapter.id = I2C_HW_B_IXP4XX;
drv_data->adapter.class = I2C_CLASS_HWMON;
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
I2C_NAME_SIZE); I2C_NAME_SIZE);
drv_data->adapter.algo_data = &drv_data->algo_data; drv_data->adapter.algo_data = &drv_data->algo_data;

View File

@@ -22,7 +22,7 @@
/* /*
Supports: Supports:
Intel PIIX4, 440MX Intel PIIX4, 440MX
Serverworks OSB4, CSB5, CSB6 Serverworks OSB4, CSB5, CSB6, HT-1000
SMSC Victory66 SMSC Victory66
Note: we assume there can only be one device, with one SMBus interface. Note: we assume there can only be one device, with one SMBus interface.
@@ -419,6 +419,8 @@ static struct pci_device_id piix4_ids[] = {
.driver_data = 0 }, .driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6),
.driver_data = 0 }, .driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB),
.driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3),
.driver_data = 3 }, .driver_data = 3 },
{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3),

View File

@@ -647,7 +647,7 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
} }
/* /*
* We are protected by the adapter bus semaphore. * We are protected by the adapter bus mutex.
*/ */
static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
{ {

View File

@@ -1,27 +1,26 @@
/* linux/drivers/i2c/scx200_acb.c /*
Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
National Semiconductor SCx200 ACCESS.bus support National Semiconductor SCx200 ACCESS.bus support
Also supports the AMD CS5535 and AMD CS5536
Based on i2c-keywest.c which is: Based on i2c-keywest.c which is:
Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/module.h> #include <linux/module.h>
@@ -32,7 +31,9 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mutex.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/msr.h>
#include <linux/scx200.h> #include <linux/scx200.h>
@@ -47,16 +48,7 @@ static int base[MAX_DEVICES] = { 0x820, 0x840 };
module_param_array(base, int, NULL, 0); module_param_array(base, int, NULL, 0);
MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
#ifdef DEBUG #define POLL_TIMEOUT (HZ/5)
#define DBG(x...) printk(KERN_DEBUG NAME ": " x)
#else
#define DBG(x...)
#endif
/* The hardware supports interrupt driven mode too, but I haven't
implemented that. */
#define POLLED_MODE 1
#define POLL_TIMEOUT (HZ)
enum scx200_acb_state { enum scx200_acb_state {
state_idle, state_idle,
@@ -79,12 +71,11 @@ static const char *scx200_acb_state_name[] = {
}; };
/* Physical interface */ /* Physical interface */
struct scx200_acb_iface struct scx200_acb_iface {
{
struct scx200_acb_iface *next; struct scx200_acb_iface *next;
struct i2c_adapter adapter; struct i2c_adapter adapter;
unsigned base; unsigned base;
struct semaphore sem; struct mutex mutex;
/* State machine data */ /* State machine data */
enum scx200_acb_state state; enum scx200_acb_state state;
@@ -100,7 +91,7 @@ struct scx200_acb_iface
#define ACBSDA (iface->base + 0) #define ACBSDA (iface->base + 0)
#define ACBST (iface->base + 1) #define ACBST (iface->base + 1)
#define ACBST_SDAST 0x40 /* SDA Status */ #define ACBST_SDAST 0x40 /* SDA Status */
#define ACBST_BER 0x20 #define ACBST_BER 0x20
#define ACBST_NEGACK 0x10 /* Negative Acknowledge */ #define ACBST_NEGACK 0x10 /* Negative Acknowledge */
#define ACBST_STASTR 0x08 /* Stall After Start */ #define ACBST_STASTR 0x08 /* Stall After Start */
#define ACBST_MASTER 0x02 #define ACBST_MASTER 0x02
@@ -109,9 +100,9 @@ struct scx200_acb_iface
#define ACBCTL1 (iface->base + 3) #define ACBCTL1 (iface->base + 3)
#define ACBCTL1_STASTRE 0x80 #define ACBCTL1_STASTRE 0x80
#define ACBCTL1_NMINTE 0x40 #define ACBCTL1_NMINTE 0x40
#define ACBCTL1_ACK 0x10 #define ACBCTL1_ACK 0x10
#define ACBCTL1_STOP 0x02 #define ACBCTL1_STOP 0x02
#define ACBCTL1_START 0x01 #define ACBCTL1_START 0x01
#define ACBADDR (iface->base + 4) #define ACBADDR (iface->base + 4)
#define ACBCTL2 (iface->base + 5) #define ACBCTL2 (iface->base + 5)
#define ACBCTL2_ENABLE 0x01 #define ACBCTL2_ENABLE 0x01
@@ -122,8 +113,8 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
{ {
const char *errmsg; const char *errmsg;
DBG("state %s, status = 0x%02x\n", dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n",
scx200_acb_state_name[iface->state], status); scx200_acb_state_name[iface->state], status);
if (status & ACBST_BER) { if (status & ACBST_BER) {
errmsg = "bus error"; errmsg = "bus error";
@@ -133,8 +124,17 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
errmsg = "not master"; errmsg = "not master";
goto error; goto error;
} }
if (status & ACBST_NEGACK) if (status & ACBST_NEGACK) {
goto negack; dev_dbg(&iface->adapter.dev, "negative ack in state %s\n",
scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -ENXIO;
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
return;
}
switch (iface->state) { switch (iface->state) {
case state_idle: case state_idle:
@@ -160,10 +160,10 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
case state_repeat_start: case state_repeat_start:
outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
/* fallthrough */ /* fallthrough */
case state_quick: case state_quick:
if (iface->address_byte & 1) { if (iface->address_byte & 1) {
if (iface->len == 1) if (iface->len == 1)
outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
else else
outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
@@ -202,26 +202,15 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
break; break;
} }
outb(*iface->ptr++, ACBSDA); outb(*iface->ptr++, ACBSDA);
--iface->len; --iface->len;
break; break;
} }
return; return;
negack:
DBG("negative acknowledge in state %s\n",
scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -ENXIO;
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
return;
error: error:
dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg,
scx200_acb_state_name[iface->state]); scx200_acb_state_name[iface->state]);
@@ -231,20 +220,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
iface->needs_reset = 1; iface->needs_reset = 1;
} }
static void scx200_acb_timeout(struct scx200_acb_iface *iface)
{
dev_err(&iface->adapter.dev, "timeout in state %s\n",
scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -EIO;
iface->needs_reset = 1;
}
#ifdef POLLED_MODE
static void scx200_acb_poll(struct scx200_acb_iface *iface) static void scx200_acb_poll(struct scx200_acb_iface *iface)
{ {
u8 status = 0; u8 status;
unsigned long timeout; unsigned long timeout;
timeout = jiffies + POLL_TIMEOUT; timeout = jiffies + POLL_TIMEOUT;
@@ -254,17 +232,21 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
scx200_acb_machine(iface, status); scx200_acb_machine(iface, status);
return; return;
} }
msleep(10); yield();
} }
scx200_acb_timeout(iface); dev_err(&iface->adapter.dev, "timeout in state %s\n",
scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -EIO;
iface->needs_reset = 1;
} }
#endif /* POLLED_MODE */
static void scx200_acb_reset(struct scx200_acb_iface *iface) static void scx200_acb_reset(struct scx200_acb_iface *iface)
{ {
/* Disable the ACCESS.bus device and Configure the SCL /* Disable the ACCESS.bus device and Configure the SCL
frequency: 16 clock cycles */ frequency: 16 clock cycles */
outb(0x70, ACBCTL2); outb(0x70, ACBCTL2);
/* Polling mode */ /* Polling mode */
outb(0, ACBCTL1); outb(0, ACBCTL1);
@@ -283,9 +265,9 @@ static void scx200_acb_reset(struct scx200_acb_iface *iface)
} }
static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
u16 address, unsigned short flags, u16 address, unsigned short flags,
char rw, u8 command, int size, char rw, u8 command, int size,
union i2c_smbus_data *data) union i2c_smbus_data *data)
{ {
struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); struct scx200_acb_iface *iface = i2c_get_adapdata(adapter);
int len; int len;
@@ -295,53 +277,47 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
switch (size) { switch (size) {
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
len = 0; len = 0;
buffer = NULL; buffer = NULL;
break; break;
case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE:
if (rw == I2C_SMBUS_READ) { len = 1;
len = 1; buffer = rw ? &data->byte : &command;
buffer = &data->byte; break;
} else {
len = 1;
buffer = &command;
}
break;
case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_BYTE_DATA:
len = 1; len = 1;
buffer = &data->byte; buffer = &data->byte;
break; break;
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
len = 2; len = 2;
cur_word = cpu_to_le16(data->word); cur_word = cpu_to_le16(data->word);
buffer = (u8 *)&cur_word; buffer = (u8 *)&cur_word;
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
len = data->block[0]; len = data->block[0];
buffer = &data->block[1]; buffer = &data->block[1];
break; break;
default: default:
return -EINVAL;
}
DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n",
size, address, command, len, rw == I2C_SMBUS_READ);
if (!len && rw == I2C_SMBUS_READ) {
dev_warn(&adapter->dev, "zero length read\n");
return -EINVAL; return -EINVAL;
} }
if (len && !buffer) { dev_dbg(&adapter->dev,
dev_warn(&adapter->dev, "nonzero length but no buffer\n"); "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n",
return -EFAULT; size, address, command, len, rw);
if (!len && rw == I2C_SMBUS_READ) {
dev_dbg(&adapter->dev, "zero length read\n");
return -EINVAL;
} }
down(&iface->sem); mutex_lock(&iface->mutex);
iface->address_byte = address<<1; iface->address_byte = (address << 1) | rw;
if (rw == I2C_SMBUS_READ)
iface->address_byte |= 1;
iface->command = command; iface->command = command;
iface->ptr = buffer; iface->ptr = buffer;
iface->len = len; iface->len = len;
@@ -355,25 +331,21 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
else else
iface->state = state_address; iface->state = state_address;
#ifdef POLLED_MODE
while (iface->state != state_idle) while (iface->state != state_idle)
scx200_acb_poll(iface); scx200_acb_poll(iface);
#else /* POLLED_MODE */
#error Interrupt driven mode not implemented
#endif /* POLLED_MODE */
if (iface->needs_reset) if (iface->needs_reset)
scx200_acb_reset(iface); scx200_acb_reset(iface);
rc = iface->result; rc = iface->result;
up(&iface->sem); mutex_unlock(&iface->mutex);
if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ)
data->word = le16_to_cpu(cur_word); data->word = le16_to_cpu(cur_word);
#ifdef DEBUG #ifdef DEBUG
DBG(": transfer done, result: %d", rc); dev_dbg(&adapter->dev, "transfer done, result: %d", rc);
if (buffer) { if (buffer) {
int i; int i;
printk(" data:"); printk(" data:");
@@ -400,17 +372,18 @@ static struct i2c_algorithm scx200_acb_algorithm = {
}; };
static struct scx200_acb_iface *scx200_acb_list; static struct scx200_acb_iface *scx200_acb_list;
static DECLARE_MUTEX(scx200_acb_list_mutex);
static int scx200_acb_probe(struct scx200_acb_iface *iface) static int scx200_acb_probe(struct scx200_acb_iface *iface)
{ {
u8 val; u8 val;
/* Disable the ACCESS.bus device and Configure the SCL /* Disable the ACCESS.bus device and Configure the SCL
frequency: 16 clock cycles */ frequency: 16 clock cycles */
outb(0x70, ACBCTL2); outb(0x70, ACBCTL2);
if (inb(ACBCTL2) != 0x70) { if (inb(ACBCTL2) != 0x70) {
DBG("ACBCTL2 readback failed\n"); pr_debug(NAME ": ACBCTL2 readback failed\n");
return -ENXIO; return -ENXIO;
} }
@@ -418,7 +391,8 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface)
val = inb(ACBCTL1); val = inb(ACBCTL1);
if (val) { if (val) {
DBG("disabled, but ACBCTL1=0x%02x\n", val); pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n",
val);
return -ENXIO; return -ENXIO;
} }
@@ -428,18 +402,19 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface)
val = inb(ACBCTL1); val = inb(ACBCTL1);
if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) {
DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); pr_debug(NAME ": enabled, but NMINTE won't be set, "
"ACBCTL1=0x%02x\n", val);
return -ENXIO; return -ENXIO;
} }
return 0; return 0;
} }
static int __init scx200_acb_create(int base, int index) static int __init scx200_acb_create(const char *text, int base, int index)
{ {
struct scx200_acb_iface *iface; struct scx200_acb_iface *iface;
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
int rc = 0; int rc;
char description[64]; char description[64];
iface = kzalloc(sizeof(*iface), GFP_KERNEL); iface = kzalloc(sizeof(*iface), GFP_KERNEL);
@@ -451,50 +426,51 @@ static int __init scx200_acb_create(int base, int index)
adapter = &iface->adapter; adapter = &iface->adapter;
i2c_set_adapdata(adapter, iface); i2c_set_adapdata(adapter, iface);
snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index);
adapter->owner = THIS_MODULE; adapter->owner = THIS_MODULE;
adapter->id = I2C_HW_SMBUS_SCX200; adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm; adapter->algo = &scx200_acb_algorithm;
adapter->class = I2C_CLASS_HWMON; adapter->class = I2C_CLASS_HWMON;
init_MUTEX(&iface->sem); mutex_init(&iface->mutex);
snprintf(description, sizeof(description), "%s ACCESS.bus [%s]",
text, adapter->name);
snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name);
if (request_region(base, 8, description) == 0) { if (request_region(base, 8, description) == 0) {
dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
base, base + 8-1); base, base + 8-1);
rc = -EBUSY; rc = -EBUSY;
goto errout; goto errout_free;
} }
iface->base = base; iface->base = base;
rc = scx200_acb_probe(iface); rc = scx200_acb_probe(iface);
if (rc) { if (rc) {
dev_warn(&adapter->dev, "probe failed\n"); printk(KERN_WARNING NAME ": probe failed\n");
goto errout; goto errout_release;
} }
scx200_acb_reset(iface); scx200_acb_reset(iface);
if (i2c_add_adapter(adapter) < 0) { if (i2c_add_adapter(adapter) < 0) {
dev_err(&adapter->dev, "failed to register\n"); printk(KERN_ERR NAME ": failed to register\n");
rc = -ENODEV; rc = -ENODEV;
goto errout; goto errout_release;
} }
lock_kernel(); down(&scx200_acb_list_mutex);
iface->next = scx200_acb_list; iface->next = scx200_acb_list;
scx200_acb_list = iface; scx200_acb_list = iface;
unlock_kernel(); up(&scx200_acb_list_mutex);
return 0; return 0;
errout_release:
release_region(iface->base, 8);
errout_free:
kfree(iface);
errout: errout:
if (iface) {
if (iface->base)
release_region(iface->base, 8);
kfree(iface);
}
return rc; return rc;
} }
@@ -504,50 +480,69 @@ static struct pci_device_id scx200[] = {
{ }, { },
}; };
static struct pci_device_id divil_pci[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
{ } /* NULL entry */
};
#define MSR_LBAR_SMB 0x5140000B
static int scx200_add_cs553x(void)
{
u32 low, hi;
u32 smb_base;
/* Grab & reserve the SMB I/O range */
rdmsr(MSR_LBAR_SMB, low, hi);
/* Check the IO mask and whether SMB is enabled */
if (hi != 0x0000F001) {
printk(KERN_WARNING NAME ": SMBus not enabled\n");
return -ENODEV;
}
/* SMBus IO size is 8 bytes */
smb_base = low & 0x0000FFF8;
return scx200_acb_create("CS5535", smb_base, 0);
}
static int __init scx200_acb_init(void) static int __init scx200_acb_init(void)
{ {
int i; int i;
int rc; int rc = -ENODEV;
pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
/* Verify that this really is a SCx200 processor */ /* Verify that this really is a SCx200 processor */
if (pci_dev_present(scx200) == 0) if (pci_dev_present(scx200)) {
return -ENODEV; for (i = 0; i < MAX_DEVICES; ++i) {
if (base[i] > 0)
rc = scx200_acb_create("SCx200", base[i], i);
}
} else if (pci_dev_present(divil_pci))
rc = scx200_add_cs553x();
rc = -ENXIO;
for (i = 0; i < MAX_DEVICES; ++i) {
if (base[i] > 0)
rc = scx200_acb_create(base[i], i);
}
if (scx200_acb_list)
return 0;
return rc; return rc;
} }
static void __exit scx200_acb_cleanup(void) static void __exit scx200_acb_cleanup(void)
{ {
struct scx200_acb_iface *iface; struct scx200_acb_iface *iface;
lock_kernel();
down(&scx200_acb_list_mutex);
while ((iface = scx200_acb_list) != NULL) { while ((iface = scx200_acb_list) != NULL) {
scx200_acb_list = iface->next; scx200_acb_list = iface->next;
unlock_kernel(); up(&scx200_acb_list_mutex);
i2c_del_adapter(&iface->adapter); i2c_del_adapter(&iface->adapter);
release_region(iface->base, 8); release_region(iface->base, 8);
kfree(iface); kfree(iface);
lock_kernel(); down(&scx200_acb_list_mutex);
} }
unlock_kernel(); up(&scx200_acb_list_mutex);
} }
module_init(scx200_acb_init); module_init(scx200_acb_init);
module_exit(scx200_acb_cleanup); module_exit(scx200_acb_cleanup);
/*
Local variables:
compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules"
c-basic-offset: 8
End:
*/

View File

@@ -26,6 +26,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/mutex.h>
#define DS1374_REG_TOD0 0x00 #define DS1374_REG_TOD0 0x00
#define DS1374_REG_TOD1 0x01 #define DS1374_REG_TOD1 0x01
@@ -41,7 +42,7 @@
#define DS1374_DRV_NAME "ds1374" #define DS1374_DRV_NAME "ds1374"
static DECLARE_MUTEX(ds1374_mutex); static DEFINE_MUTEX(ds1374_mutex);
static struct i2c_driver ds1374_driver; static struct i2c_driver ds1374_driver;
static struct i2c_client *save_client; static struct i2c_client *save_client;
@@ -114,7 +115,7 @@ ulong ds1374_get_rtc_time(void)
ulong t1, t2; ulong t1, t2;
int limit = 10; /* arbitrary retry limit */ int limit = 10; /* arbitrary retry limit */
down(&ds1374_mutex); mutex_lock(&ds1374_mutex);
/* /*
* Since the reads are being performed one byte at a time using * Since the reads are being performed one byte at a time using
@@ -127,7 +128,7 @@ ulong ds1374_get_rtc_time(void)
t2 = ds1374_read_rtc(); t2 = ds1374_read_rtc();
} while (t1 != t2 && limit--); } while (t1 != t2 && limit--);
up(&ds1374_mutex); mutex_unlock(&ds1374_mutex);
if (t1 != t2) { if (t1 != t2) {
dev_warn(&save_client->dev, dev_warn(&save_client->dev,
@@ -145,7 +146,7 @@ static void ds1374_set_tlet(ulong arg)
t1 = *(ulong *) arg; t1 = *(ulong *) arg;
down(&ds1374_mutex); mutex_lock(&ds1374_mutex);
/* /*
* Since the writes are being performed one byte at a time using * Since the writes are being performed one byte at a time using
@@ -158,7 +159,7 @@ static void ds1374_set_tlet(ulong arg)
t2 = ds1374_read_rtc(); t2 = ds1374_read_rtc();
} while (t1 != t2 && limit--); } while (t1 != t2 && limit--);
up(&ds1374_mutex); mutex_unlock(&ds1374_mutex);
if (t1 != t2) if (t1 != t2)
dev_warn(&save_client->dev, dev_warn(&save_client->dev,

View File

@@ -33,6 +33,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
@@ -54,7 +55,7 @@ enum eeprom_nature {
/* Each client has this additional data */ /* Each client has this additional data */
struct eeprom_data { struct eeprom_data {
struct i2c_client client; struct i2c_client client;
struct semaphore update_lock; struct mutex update_lock;
u8 valid; /* bitfield, bit!=0 if slice is valid */ u8 valid; /* bitfield, bit!=0 if slice is valid */
unsigned long last_updated[8]; /* In jiffies, 8 slices */ unsigned long last_updated[8]; /* In jiffies, 8 slices */
u8 data[EEPROM_SIZE]; /* Register values */ u8 data[EEPROM_SIZE]; /* Register values */
@@ -81,7 +82,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
struct eeprom_data *data = i2c_get_clientdata(client); struct eeprom_data *data = i2c_get_clientdata(client);
int i, j; int i, j;
down(&data->update_lock); mutex_lock(&data->update_lock);
if (!(data->valid & (1 << slice)) || if (!(data->valid & (1 << slice)) ||
time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
@@ -107,7 +108,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
data->valid |= (1 << slice); data->valid |= (1 << slice);
} }
exit: exit:
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
@@ -187,7 +188,7 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields */ /* Fill in the remaining client fields */
strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE);
data->valid = 0; data->valid = 0;
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
data->nature = UNKNOWN; data->nature = UNKNOWN;
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */

View File

@@ -1635,8 +1635,6 @@ static struct i2c_driver isp1301_driver = {
.driver = { .driver = {
.name = "isp1301_omap", .name = "isp1301_omap",
}, },
.id = 1301, /* FIXME "official", i2c-ids.h */
.class = I2C_CLASS_HWMON,
.attach_adapter = isp1301_scan_bus, .attach_adapter = isp1301_scan_bus,
.detach_client = isp1301_detach_client, .detach_client = isp1301_detach_client,
}; };

View File

@@ -24,13 +24,14 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/mutex.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/rtc.h> #include <asm/rtc.h>
#define M41T00_DRV_NAME "m41t00" #define M41T00_DRV_NAME "m41t00"
static DECLARE_MUTEX(m41t00_mutex); static DEFINE_MUTEX(m41t00_mutex);
static struct i2c_driver m41t00_driver; static struct i2c_driver m41t00_driver;
static struct i2c_client *save_client; static struct i2c_client *save_client;
@@ -54,7 +55,7 @@ m41t00_get_rtc_time(void)
sec = min = hour = day = mon = year = 0; sec = min = hour = day = mon = year = 0;
sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; sec1 = min1 = hour1 = day1 = mon1 = year1 = 0;
down(&m41t00_mutex); mutex_lock(&m41t00_mutex);
do { do {
if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0)
&& ((min = i2c_smbus_read_byte_data(save_client, 1)) && ((min = i2c_smbus_read_byte_data(save_client, 1))
@@ -80,7 +81,7 @@ m41t00_get_rtc_time(void)
mon1 = mon; mon1 = mon;
year1 = year; year1 = year;
} while (--limit > 0); } while (--limit > 0);
up(&m41t00_mutex); mutex_unlock(&m41t00_mutex);
if (limit == 0) { if (limit == 0) {
dev_warn(&save_client->dev, dev_warn(&save_client->dev,
@@ -125,7 +126,7 @@ m41t00_set_tlet(ulong arg)
BIN_TO_BCD(tm.tm_mday); BIN_TO_BCD(tm.tm_mday);
BIN_TO_BCD(tm.tm_year); BIN_TO_BCD(tm.tm_year);
down(&m41t00_mutex); mutex_lock(&m41t00_mutex);
if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
< 0) < 0)
@@ -140,7 +141,7 @@ m41t00_set_tlet(ulong arg)
dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
up(&m41t00_mutex); mutex_unlock(&m41t00_mutex);
return; return;
} }

View File

@@ -31,7 +31,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <asm/semaphore.h> #include <linux/mutex.h>
/* Do not scan - the MAX6875 access method will write to some EEPROM chips */ /* Do not scan - the MAX6875 access method will write to some EEPROM chips */
static unsigned short normal_i2c[] = {I2C_CLIENT_END}; static unsigned short normal_i2c[] = {I2C_CLIENT_END};
@@ -54,7 +54,7 @@ I2C_CLIENT_INSMOD_1(max6875);
/* Each client has this additional data */ /* Each client has this additional data */
struct max6875_data { struct max6875_data {
struct i2c_client client; struct i2c_client client;
struct semaphore update_lock; struct mutex update_lock;
u32 valid; u32 valid;
u8 data[USER_EEPROM_SIZE]; u8 data[USER_EEPROM_SIZE];
@@ -83,7 +83,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice)
if (slice >= USER_EEPROM_SLICES) if (slice >= USER_EEPROM_SLICES)
return; return;
down(&data->update_lock); mutex_lock(&data->update_lock);
buf = &data->data[slice << SLICE_BITS]; buf = &data->data[slice << SLICE_BITS];
@@ -122,7 +122,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice)
data->valid |= (1 << slice); data->valid |= (1 << slice);
} }
exit_up: exit_up:
up(&data->update_lock); mutex_unlock(&data->update_lock);
} }
static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
@@ -196,7 +196,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
real_client->driver = &max6875_driver; real_client->driver = &max6875_driver;
real_client->flags = 0; real_client->flags = 0;
strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Init fake client data */ /* Init fake client data */
/* set the client data to the i2c_client so that it will get freed */ /* set the client data to the i2c_client so that it will get freed */

View File

@@ -24,6 +24,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mutex.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
@@ -74,7 +75,7 @@ MODULE_PARM_DESC(input_mode,
struct pcf8591_data { struct pcf8591_data {
struct i2c_client client; struct i2c_client client;
struct semaphore update_lock; struct mutex update_lock;
u8 control; u8 control;
u8 aout; u8 aout;
@@ -144,13 +145,13 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
struct pcf8591_data *data = i2c_get_clientdata(client); struct pcf8591_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); mutex_lock(&data->update_lock);
if (val) if (val)
data->control |= PCF8591_CONTROL_AOEF; data->control |= PCF8591_CONTROL_AOEF;
else else
data->control &= ~PCF8591_CONTROL_AOEF; data->control &= ~PCF8591_CONTROL_AOEF;
i2c_smbus_write_byte(client, data->control); i2c_smbus_write_byte(client, data->control);
up(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
@@ -200,7 +201,7 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global /* Fill in the remaining client fields and put it into the global
list */ list */
strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE);
init_MUTEX(&data->update_lock); mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
@@ -265,7 +266,7 @@ static int pcf8591_read_channel(struct device *dev, int channel)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct pcf8591_data *data = i2c_get_clientdata(client); struct pcf8591_data *data = i2c_get_clientdata(client);
down(&data->update_lock); mutex_lock(&data->update_lock);
if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) {
data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK)
@@ -278,7 +279,7 @@ static int pcf8591_read_channel(struct device *dev, int channel)
} }
value = i2c_smbus_read_byte(client); value = i2c_smbus_read_byte(client);
up(&data->update_lock); mutex_unlock(&data->update_lock);
if ((channel == 2 && input_mode == 2) || if ((channel == 2 && input_mode == 2) ||
(channel != 3 && (input_mode == 1 || input_mode == 3))) (channel != 3 && (input_mode == 1 || input_mode == 3)))

View File

@@ -32,6 +32,7 @@
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/mutex.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@@ -81,7 +82,7 @@ enum tps_model {
struct tps65010 { struct tps65010 {
struct i2c_client client; struct i2c_client client;
struct semaphore lock; struct mutex lock;
int irq; int irq;
struct work_struct work; struct work_struct work;
struct dentry *file; struct dentry *file;
@@ -218,7 +219,7 @@ static int dbg_show(struct seq_file *s, void *_)
seq_printf(s, "driver %s\nversion %s\nchip %s\n\n", seq_printf(s, "driver %s\nversion %s\nchip %s\n\n",
DRIVER_NAME, DRIVER_VERSION, chip); DRIVER_NAME, DRIVER_VERSION, chip);
down(&tps->lock); mutex_lock(&tps->lock);
/* FIXME how can we tell whether a battery is present? /* FIXME how can we tell whether a battery is present?
* likely involves a charge gauging chip (like BQ26501). * likely involves a charge gauging chip (like BQ26501).
@@ -300,7 +301,7 @@ static int dbg_show(struct seq_file *s, void *_)
(v2 & (1 << (4 + i))) ? "rising" : "falling"); (v2 & (1 << (4 + i))) ? "rising" : "falling");
} }
up(&tps->lock); mutex_unlock(&tps->lock);
return 0; return 0;
} }
@@ -416,7 +417,7 @@ static void tps65010_work(void *_tps)
{ {
struct tps65010 *tps = _tps; struct tps65010 *tps = _tps;
down(&tps->lock); mutex_lock(&tps->lock);
tps65010_interrupt(tps); tps65010_interrupt(tps);
@@ -444,7 +445,7 @@ static void tps65010_work(void *_tps)
if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags)) if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
enable_irq(tps->irq); enable_irq(tps->irq);
up(&tps->lock); mutex_unlock(&tps->lock);
} }
static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs) static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs)
@@ -505,7 +506,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
if (!tps) if (!tps)
return 0; return 0;
init_MUTEX(&tps->lock); mutex_init(&tps->lock);
INIT_WORK(&tps->work, tps65010_work, tps); INIT_WORK(&tps->work, tps65010_work, tps);
tps->irq = -1; tps->irq = -1;
tps->client.addr = address; tps->client.addr = address;
@@ -695,7 +696,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
if ((gpio < GPIO1) || (gpio > GPIO4)) if ((gpio < GPIO1) || (gpio > GPIO4))
return -EINVAL; return -EINVAL;
down(&the_tps->lock); mutex_lock(&the_tps->lock);
defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO); defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO);
@@ -720,7 +721,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
gpio, value ? "high" : "low", gpio, value ? "high" : "low",
i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO)); i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO));
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
EXPORT_SYMBOL(tps65010_set_gpio_out_value); EXPORT_SYMBOL(tps65010_set_gpio_out_value);
@@ -745,7 +746,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
led = LED2; led = LED2;
} }
down(&the_tps->lock); mutex_lock(&the_tps->lock);
pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led,
i2c_smbus_read_byte_data(&the_tps->client, i2c_smbus_read_byte_data(&the_tps->client,
@@ -771,7 +772,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
default: default:
printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n", printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n",
DRIVER_NAME); DRIVER_NAME);
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return -EINVAL; return -EINVAL;
} }
@@ -781,7 +782,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
if (status != 0) { if (status != 0) {
printk(KERN_ERR "%s: Failed to write led%i_on register\n", printk(KERN_ERR "%s: Failed to write led%i_on register\n",
DRIVER_NAME, led); DRIVER_NAME, led);
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
@@ -794,7 +795,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
if (status != 0) { if (status != 0) {
printk(KERN_ERR "%s: Failed to write led%i_per register\n", printk(KERN_ERR "%s: Failed to write led%i_per register\n",
DRIVER_NAME, led); DRIVER_NAME, led);
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
@@ -802,7 +803,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
i2c_smbus_read_byte_data(&the_tps->client, i2c_smbus_read_byte_data(&the_tps->client,
TPS_LED1_PER + offs)); TPS_LED1_PER + offs));
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
@@ -820,7 +821,7 @@ int tps65010_set_vib(unsigned value)
if (!the_tps) if (!the_tps)
return -ENODEV; return -ENODEV;
down(&the_tps->lock); mutex_lock(&the_tps->lock);
vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2); vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2);
vdcdc2 &= ~(1 << 1); vdcdc2 &= ~(1 << 1);
@@ -831,7 +832,7 @@ int tps65010_set_vib(unsigned value)
pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off"); pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off");
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
EXPORT_SYMBOL(tps65010_set_vib); EXPORT_SYMBOL(tps65010_set_vib);
@@ -848,7 +849,7 @@ int tps65010_set_low_pwr(unsigned mode)
if (!the_tps) if (!the_tps)
return -ENODEV; return -ENODEV;
down(&the_tps->lock); mutex_lock(&the_tps->lock);
pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME, pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME,
mode ? "enable" : "disable", mode ? "enable" : "disable",
@@ -876,7 +877,7 @@ int tps65010_set_low_pwr(unsigned mode)
pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
@@ -894,7 +895,7 @@ int tps65010_config_vregs1(unsigned value)
if (!the_tps) if (!the_tps)
return -ENODEV; return -ENODEV;
down(&the_tps->lock); mutex_lock(&the_tps->lock);
pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
@@ -909,7 +910,7 @@ int tps65010_config_vregs1(unsigned value)
pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
@@ -931,7 +932,7 @@ int tps65013_set_low_pwr(unsigned mode)
if (!the_tps || the_tps->por) if (!the_tps || the_tps->por)
return -ENODEV; return -ENODEV;
down(&the_tps->lock); mutex_lock(&the_tps->lock);
pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n", pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n",
DRIVER_NAME, DRIVER_NAME,
@@ -959,7 +960,7 @@ int tps65013_set_low_pwr(unsigned mode)
if (status != 0) { if (status != 0) {
printk(KERN_ERR "%s: Failed to write chconfig register\n", printk(KERN_ERR "%s: Failed to write chconfig register\n",
DRIVER_NAME); DRIVER_NAME);
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }
@@ -977,7 +978,7 @@ int tps65013_set_low_pwr(unsigned mode)
pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
up(&the_tps->lock); mutex_unlock(&the_tps->lock);
return status; return status;
} }

View File

@@ -31,12 +31,13 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mutex.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
static LIST_HEAD(adapters); static LIST_HEAD(adapters);
static LIST_HEAD(drivers); static LIST_HEAD(drivers);
static DECLARE_MUTEX(core_lists); static DEFINE_MUTEX(core_lists);
static DEFINE_IDR(i2c_adapter_idr); static DEFINE_IDR(i2c_adapter_idr);
/* match always succeeds, as we want the probe() to tell if we really accept this match */ /* match always succeeds, as we want the probe() to tell if we really accept this match */
@@ -153,7 +154,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
struct list_head *item; struct list_head *item;
struct i2c_driver *driver; struct i2c_driver *driver;
down(&core_lists); mutex_lock(&core_lists);
if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
res = -ENOMEM; res = -ENOMEM;
@@ -168,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
} }
adap->nr = id & MAX_ID_MASK; adap->nr = id & MAX_ID_MASK;
init_MUTEX(&adap->bus_lock); mutex_init(&adap->bus_lock);
init_MUTEX(&adap->clist_lock); mutex_init(&adap->clist_lock);
list_add_tail(&adap->list,&adapters); list_add_tail(&adap->list,&adapters);
INIT_LIST_HEAD(&adap->clients); INIT_LIST_HEAD(&adap->clients);
@@ -203,7 +204,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
} }
out_unlock: out_unlock:
up(&core_lists); mutex_unlock(&core_lists);
return res; return res;
} }
@@ -216,7 +217,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
struct i2c_client *client; struct i2c_client *client;
int res = 0; int res = 0;
down(&core_lists); mutex_lock(&core_lists);
/* First make sure that this adapter was ever added */ /* First make sure that this adapter was ever added */
list_for_each_entry(adap_from_list, &adapters, list) { list_for_each_entry(adap_from_list, &adapters, list) {
@@ -272,7 +273,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
out_unlock: out_unlock:
up(&core_lists); mutex_unlock(&core_lists);
return res; return res;
} }
@@ -287,9 +288,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{ {
struct list_head *item; struct list_head *item;
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
int res = 0; int res;
down(&core_lists);
/* add the driver to the list of i2c drivers in the driver core */ /* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner; driver->driver.owner = owner;
@@ -297,8 +296,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
res = driver_register(&driver->driver); res = driver_register(&driver->driver);
if (res) if (res)
goto out_unlock; return res;
mutex_lock(&core_lists);
list_add_tail(&driver->list,&drivers); list_add_tail(&driver->list,&drivers);
pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
@@ -310,9 +311,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
} }
} }
out_unlock: mutex_unlock(&core_lists);
up(&core_lists); return 0;
return res;
} }
EXPORT_SYMBOL(i2c_register_driver); EXPORT_SYMBOL(i2c_register_driver);
@@ -324,7 +324,7 @@ int i2c_del_driver(struct i2c_driver *driver)
int res = 0; int res = 0;
down(&core_lists); mutex_lock(&core_lists);
/* Have a look at each adapter, if clients of this driver are still /* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver * attached. If so, detach them to be able to kill the driver
@@ -363,7 +363,7 @@ int i2c_del_driver(struct i2c_driver *driver)
pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
out_unlock: out_unlock:
up(&core_lists); mutex_unlock(&core_lists);
return 0; return 0;
} }
@@ -384,9 +384,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
{ {
int rval; int rval;
down(&adapter->clist_lock); mutex_lock(&adapter->clist_lock);
rval = __i2c_check_addr(adapter, addr); rval = __i2c_check_addr(adapter, addr);
up(&adapter->clist_lock); mutex_unlock(&adapter->clist_lock);
return rval; return rval;
} }
@@ -395,13 +395,13 @@ int i2c_attach_client(struct i2c_client *client)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
down(&adapter->clist_lock); mutex_lock(&adapter->clist_lock);
if (__i2c_check_addr(client->adapter, client->addr)) { if (__i2c_check_addr(client->adapter, client->addr)) {
up(&adapter->clist_lock); mutex_unlock(&adapter->clist_lock);
return -EBUSY; return -EBUSY;
} }
list_add_tail(&client->list,&adapter->clients); list_add_tail(&client->list,&adapter->clients);
up(&adapter->clist_lock); mutex_unlock(&adapter->clist_lock);
if (adapter->client_register) { if (adapter->client_register) {
if (adapter->client_register(client)) { if (adapter->client_register(client)) {
@@ -450,12 +450,12 @@ int i2c_detach_client(struct i2c_client *client)
} }
} }
down(&adapter->clist_lock); mutex_lock(&adapter->clist_lock);
list_del(&client->list); list_del(&client->list);
init_completion(&client->released); init_completion(&client->released);
device_remove_file(&client->dev, &dev_attr_client_name); device_remove_file(&client->dev, &dev_attr_client_name);
device_unregister(&client->dev); device_unregister(&client->dev);
up(&adapter->clist_lock); mutex_unlock(&adapter->clist_lock);
wait_for_completion(&client->released); wait_for_completion(&client->released);
out: out:
@@ -513,19 +513,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
struct list_head *item; struct list_head *item;
struct i2c_client *client; struct i2c_client *client;
down(&adap->clist_lock); mutex_lock(&adap->clist_lock);
list_for_each(item,&adap->clients) { list_for_each(item,&adap->clients) {
client = list_entry(item, struct i2c_client, list); client = list_entry(item, struct i2c_client, list);
if (!try_module_get(client->driver->driver.owner)) if (!try_module_get(client->driver->driver.owner))
continue; continue;
if (NULL != client->driver->command) { if (NULL != client->driver->command) {
up(&adap->clist_lock); mutex_unlock(&adap->clist_lock);
client->driver->command(client,cmd,arg); client->driver->command(client,cmd,arg);
down(&adap->clist_lock); mutex_lock(&adap->clist_lock);
} }
module_put(client->driver->driver.owner); module_put(client->driver->driver.owner);
} }
up(&adap->clist_lock); mutex_unlock(&adap->clist_lock);
} }
static int __init i2c_init(void) static int __init i2c_init(void)
@@ -569,9 +569,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
} }
#endif #endif
down(&adap->bus_lock); mutex_lock(&adap->bus_lock);
ret = adap->algo->master_xfer(adap,msgs,num); ret = adap->algo->master_xfer(adap,msgs,num);
up(&adap->bus_lock); mutex_unlock(&adap->bus_lock);
return ret; return ret;
} else { } else {
@@ -779,12 +779,12 @@ struct i2c_adapter* i2c_get_adapter(int id)
{ {
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
down(&core_lists); mutex_lock(&core_lists);
adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
if (adapter && !try_module_get(adapter->owner)) if (adapter && !try_module_get(adapter->owner))
adapter = NULL; adapter = NULL;
up(&core_lists); mutex_unlock(&core_lists);
return adapter; return adapter;
} }
@@ -919,12 +919,11 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
u8 length, u8 *values) u8 length, u8 *values)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int i;
if (length > I2C_SMBUS_BLOCK_MAX) if (length > I2C_SMBUS_BLOCK_MAX)
length = I2C_SMBUS_BLOCK_MAX; length = I2C_SMBUS_BLOCK_MAX;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length; data.block[0] = length;
memcpy(&data.block[1], values, length);
return i2c_smbus_xfer(client->adapter,client->addr,client->flags, return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,command, I2C_SMBUS_WRITE,command,
I2C_SMBUS_BLOCK_DATA,&data); I2C_SMBUS_BLOCK_DATA,&data);
@@ -934,16 +933,14 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int i;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_READ,command, I2C_SMBUS_READ,command,
I2C_SMBUS_I2C_BLOCK_DATA,&data)) I2C_SMBUS_I2C_BLOCK_DATA,&data))
return -1; return -1;
else {
for (i = 1; i <= data.block[0]; i++) memcpy(values, &data.block[1], data.block[0]);
values[i-1] = data.block[i]; return data.block[0];
return data.block[0];
}
} }
s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
@@ -1118,10 +1115,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
flags &= I2C_M_TEN | I2C_CLIENT_PEC; flags &= I2C_M_TEN | I2C_CLIENT_PEC;
if (adapter->algo->smbus_xfer) { if (adapter->algo->smbus_xfer) {
down(&adapter->bus_lock); mutex_lock(&adapter->bus_lock);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
command,size,data); command,size,data);
up(&adapter->bus_lock); mutex_unlock(&adapter->bus_lock);
} else } else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data); command,size,data);

View File

@@ -53,7 +53,6 @@ MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(x) (x)->name #define I2C_NAME(x) (x)->name

View File

@@ -49,7 +49,6 @@ MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(s) (s)->name #define I2C_NAME(s) (s)->name

View File

@@ -53,7 +53,6 @@ MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(s) (s)->name #define I2C_NAME(s) (s)->name

View File

@@ -53,7 +53,6 @@ MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(s) (s)->name #define I2C_NAME(s) (s)->name

View File

@@ -39,7 +39,6 @@ MODULE_AUTHOR("Pauline Middelink");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(s) (s)->name #define I2C_NAME(s) (s)->name

View File

@@ -52,7 +52,6 @@ MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(s) (s)->name #define I2C_NAME(s) (s)->name

View File

@@ -55,7 +55,6 @@ MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(x) (x)->name #define I2C_NAME(x) (x)->name

View File

@@ -45,7 +45,6 @@ MODULE_AUTHOR("Dave Perks, Jose Ignacio Gijon, Joerg Heckenbach, Mark McClelland
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(s) (s)->name #define I2C_NAME(s) (s)->name

View File

@@ -49,7 +49,6 @@ MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(s) (s)->name #define I2C_NAME(s) (s)->name

View File

@@ -30,7 +30,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_NAME(x) (x)->name #define I2C_NAME(x) (x)->name

View File

@@ -27,11 +27,13 @@ struct sensor_device_attribute{
#define to_sensor_dev_attr(_dev_attr) \ #define to_sensor_dev_attr(_dev_attr) \
container_of(_dev_attr, struct sensor_device_attribute, dev_attr) container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index) \ #define SENSOR_ATTR(_name, _mode, _show, _store, _index) \
struct sensor_device_attribute sensor_dev_attr_##_name = { \ { .dev_attr = __ATTR(_name, _mode, _show, _store), \
.dev_attr = __ATTR(_name,_mode,_show,_store), \ .index = _index }
.index = _index, \
} #define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \
struct sensor_device_attribute sensor_dev_attr_##_name \
= SENSOR_ATTR(_name, _mode, _show, _store, _index)
struct sensor_device_attribute_2 { struct sensor_device_attribute_2 {
struct device_attribute dev_attr; struct device_attribute dev_attr;
@@ -41,11 +43,13 @@ struct sensor_device_attribute_2 {
#define to_sensor_dev_attr_2(_dev_attr) \ #define to_sensor_dev_attr_2(_dev_attr) \
container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr) container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr)
#define SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) \
{ .dev_attr = __ATTR(_name, _mode, _show, _store), \
.index = _index, \
.nr = _nr }
#define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \ #define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \
struct sensor_device_attribute_2 sensor_dev_attr_##_name = { \ struct sensor_device_attribute_2 sensor_dev_attr_##_name \
.dev_attr = __ATTR(_name,_mode,_show,_store), \ = SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index)
.index = _index, \
.nr = _nr, \
}
#endif /* _LINUX_HWMON_SYSFS_H */ #endif /* _LINUX_HWMON_SYSFS_H */

View File

@@ -172,7 +172,6 @@
#define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */
#define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */
#define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */ #define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */
#define I2C_HW_B_FRODO 0x010013 /* 2d3D SA-1110 Development Board */
#define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */ #define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */
#define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */ #define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */
#define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */

View File

@@ -32,7 +32,7 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/device.h> /* for struct device */ #include <linux/device.h> /* for struct device */
#include <linux/sched.h> /* for completion */ #include <linux/sched.h> /* for completion */
#include <asm/semaphore.h> #include <linux/mutex.h>
/* --- For i2c-isa ---------------------------------------------------- */ /* --- For i2c-isa ---------------------------------------------------- */
@@ -225,8 +225,8 @@ struct i2c_adapter {
int (*client_unregister)(struct i2c_client *); int (*client_unregister)(struct i2c_client *);
/* data fields that are valid for all devices */ /* data fields that are valid for all devices */
struct semaphore bus_lock; struct mutex bus_lock;
struct semaphore clist_lock; struct mutex clist_lock;
int timeout; int timeout;
int retries; int retries;

View File

@@ -1371,6 +1371,7 @@
#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200
#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201
#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203
#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205
#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212
#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213

View File

@@ -88,8 +88,6 @@
#include <linux/pmu.h> #include <linux/pmu.h>
#endif #endif
#include <linux/i2c-dev.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>

View File

@@ -22,7 +22,6 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <sound/core.h> #include <sound/core.h>

View File

@@ -23,7 +23,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c-dev.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <sound/core.h> #include <sound/core.h>
#include "pmac.h" #include "pmac.h"

View File

@@ -22,7 +22,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>

View File

@@ -28,7 +28,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>