diff options
Diffstat (limited to 'drivers/hwmon/gl520sm.c')
-rw-r--r-- | drivers/hwmon/gl520sm.c | 648 |
1 files changed, 389 insertions, 259 deletions
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 2d39d8fc2389..03ecdc334764 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -27,6 +27,7 @@ #include <linux/jiffies.h> #include <linux/i2c.h> #include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> #include <linux/err.h> #include <linux/mutex.h> @@ -43,9 +44,9 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD_1(gl520sm); -/* Many GL520 constants specified below +/* Many GL520 constants specified below One of the inputs can be configured as either temp or voltage. -That's why _TEMP2 and _IN4 access the same register +That's why _TEMP2 and _IN4 access the same register */ /* The GL520 registers */ @@ -56,37 +57,14 @@ That's why _TEMP2 and _IN4 access the same register #define GL520_REG_VID_INPUT 0x02 -#define GL520_REG_IN0_INPUT 0x15 -#define GL520_REG_IN0_LIMIT 0x0c -#define GL520_REG_IN0_MIN GL520_REG_IN0_LIMIT -#define GL520_REG_IN0_MAX GL520_REG_IN0_LIMIT +static const u8 GL520_REG_IN_INPUT[] = { 0x15, 0x14, 0x13, 0x0d, 0x0e }; +static const u8 GL520_REG_IN_LIMIT[] = { 0x0c, 0x09, 0x0a, 0x0b }; +static const u8 GL520_REG_IN_MIN[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x18 }; +static const u8 GL520_REG_IN_MAX[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x17 }; -#define GL520_REG_IN1_INPUT 0x14 -#define GL520_REG_IN1_LIMIT 0x09 -#define GL520_REG_IN1_MIN GL520_REG_IN1_LIMIT -#define GL520_REG_IN1_MAX GL520_REG_IN1_LIMIT - -#define GL520_REG_IN2_INPUT 0x13 -#define GL520_REG_IN2_LIMIT 0x0a -#define GL520_REG_IN2_MIN GL520_REG_IN2_LIMIT -#define GL520_REG_IN2_MAX GL520_REG_IN2_LIMIT - -#define GL520_REG_IN3_INPUT 0x0d -#define GL520_REG_IN3_LIMIT 0x0b -#define GL520_REG_IN3_MIN GL520_REG_IN3_LIMIT -#define GL520_REG_IN3_MAX GL520_REG_IN3_LIMIT - -#define GL520_REG_IN4_INPUT 0x0e -#define GL520_REG_IN4_MAX 0x17 -#define GL520_REG_IN4_MIN 0x18 - -#define GL520_REG_TEMP1_INPUT 0x04 -#define GL520_REG_TEMP1_MAX 0x05 -#define GL520_REG_TEMP1_MAX_HYST 0x06 - -#define GL520_REG_TEMP2_INPUT 0x0e -#define GL520_REG_TEMP2_MAX 0x17 -#define GL520_REG_TEMP2_MAX_HYST 0x18 +static const u8 GL520_REG_TEMP_INPUT[] = { 0x04, 0x0e }; +static const u8 GL520_REG_TEMP_MAX[] = { 0x05, 0x17 }; +static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; #define GL520_REG_FAN_INPUT 0x07 #define GL520_REG_FAN_MIN 0x08 @@ -114,7 +92,6 @@ static struct i2c_driver gl520_driver = { .driver = { .name = "gl520sm", }, - .id = I2C_DRIVERID_GL520, .attach_adapter = gl520_attach_adapter, .detach_client = gl520_detach_client, }; @@ -150,93 +127,13 @@ struct gl520_data { * Sysfs stuff */ -#define sysfs_r(type, n, item, reg) \ -static ssize_t get_##type##item (struct gl520_data *, char *, int); \ -static ssize_t get_##type##n##item (struct device *, struct device_attribute *attr, char *); \ -static ssize_t get_##type##n##item (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct gl520_data *data = gl520_update_device(dev); \ - return get_##type##item(data, buf, (n)); \ -} - -#define sysfs_w(type, n, item, reg) \ -static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \ -static ssize_t set_##type##n##item (struct device *, struct device_attribute *attr, const char *, size_t); \ -static ssize_t set_##type##n##item (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct gl520_data *data = i2c_get_clientdata(client); \ - return set_##type##item(client, data, buf, count, (n), reg); \ -} - -#define sysfs_rw_n(type, n, item, reg) \ -sysfs_r(type, n, item, reg) \ -sysfs_w(type, n, item, reg) \ -static DEVICE_ATTR(type##n##item, S_IRUGO | S_IWUSR, get_##type##n##item, set_##type##n##item); - -#define sysfs_ro_n(type, n, item, reg) \ -sysfs_r(type, n, item, reg) \ -static DEVICE_ATTR(type##n##item, S_IRUGO, get_##type##n##item, NULL); - -#define sysfs_rw(type, item, reg) \ -sysfs_r(type, 0, item, reg) \ -sysfs_w(type, 0, item, reg) \ -static DEVICE_ATTR(type##item, S_IRUGO | S_IWUSR, get_##type##0##item, set_##type##0##item); - -#define sysfs_ro(type, item, reg) \ -sysfs_r(type, 0, item, reg) \ -static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL); - - -#define sysfs_vid(n) \ -sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT) - -#define sysfs_in(n) \ -sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \ -sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \ -sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \ - -#define sysfs_fan(n) \ -sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \ -sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \ -sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV) - -#define sysfs_fan_off(n) \ -sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \ - -#define sysfs_temp(n) \ -sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \ -sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \ -sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST) - -#define sysfs_alarms() \ -sysfs_ro(alarms, , GL520_REG_ALARMS) \ -sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \ -sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK) - - -sysfs_vid(0) - -sysfs_in(0) -sysfs_in(1) -sysfs_in(2) -sysfs_in(3) -sysfs_in(4) - -sysfs_fan(1) -sysfs_fan(2) -sysfs_fan_off(1) - -sysfs_temp(1) -sysfs_temp(2) - -sysfs_alarms() - - -static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n) +static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); } +static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL); #define VDD_FROM_REG(val) (((val)*95+2)/4) #define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255)) @@ -244,8 +141,11 @@ static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n) #define IN_FROM_REG(val) ((val)*19) #define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255)) -static ssize_t get_in_input(struct gl520_data *data, char *buf, int n) +static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, + char *buf) { + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); u8 r = data->in_input[n]; if (n == 0) @@ -254,8 +154,11 @@ static ssize_t get_in_input(struct gl520_data *data, char *buf, int n) return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t get_in_min(struct gl520_data *data, char *buf, int n) +static ssize_t get_in_min(struct device *dev, struct device_attribute *attr, + char *buf) { + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); u8 r = data->in_min[n]; if (n == 0) @@ -264,8 +167,11 @@ static ssize_t get_in_min(struct gl520_data *data, char *buf, int n) return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t get_in_max(struct gl520_data *data, char *buf, int n) +static ssize_t get_in_max(struct device *dev, struct device_attribute *attr, + char *buf) { + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); u8 r = data->in_max[n]; if (n == 0) @@ -274,8 +180,12 @@ static ssize_t get_in_max(struct gl520_data *data, char *buf, int n) return sprintf(buf, "%d\n", IN_FROM_REG(r)); } -static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); u8 r; @@ -289,16 +199,22 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co data->in_min[n] = r; if (n < 4) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r); + gl520_write_value(client, GL520_REG_IN_MIN[n], + (gl520_read_value(client, GL520_REG_IN_MIN[n]) + & ~0xff) | r); else - gl520_write_value(client, reg, r); + gl520_write_value(client, GL520_REG_IN_MIN[n], r); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); u8 r; @@ -312,57 +228,109 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co data->in_max[n] = r; if (n < 4) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8)); + gl520_write_value(client, GL520_REG_IN_MAX[n], + (gl520_read_value(client, GL520_REG_IN_MAX[n]) + & ~0xff00) | (r << 8)); else - gl520_write_value(client, reg, r); + gl520_write_value(client, GL520_REG_IN_MAX[n], r); mutex_unlock(&data->update_lock); return count; } +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, get_in_input, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, get_in_input, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, get_in_input, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, get_in_input, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, get_in_input, NULL, 4); +static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 0); +static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 1); +static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 2); +static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 3); +static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR, + get_in_min, set_in_min, 4); +static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 0); +static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 1); +static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 2); +static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 3); +static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, + get_in_max, set_in_max, 4); + #define DIV_FROM_REG(val) (1 << (val)) #define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div)))) #define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255)); -static ssize_t get_fan_input(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n - 1], data->fan_div[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n], + data->fan_div[n])); } -static ssize_t get_fan_min(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n - 1], data->fan_div[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n], + data->fan_div[n])); } -static ssize_t get_fan_div(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n])); } -static ssize_t get_fan_off(struct gl520_data *data, char *buf, int n) +static ssize_t get_fan_off(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->fan_off); } -static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; unsigned long v = simple_strtoul(buf, NULL, 10); u8 r; mutex_lock(&data->update_lock); - r = FAN_TO_REG(v, data->fan_div[n - 1]); - data->fan_min[n - 1] = r; + r = FAN_TO_REG(v, data->fan_div[n]); + data->fan_min[n] = r; - if (n == 1) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8)); + if (n == 0) + gl520_write_value(client, GL520_REG_FAN_MIN, + (gl520_read_value(client, GL520_REG_FAN_MIN) + & ~0xff00) | (r << 8)); else - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r); + gl520_write_value(client, GL520_REG_FAN_MIN, + (gl520_read_value(client, GL520_REG_FAN_MIN) + & ~0xff) | r); data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); - if (data->fan_min[n - 1] == 0) - data->alarm_mask &= (n == 1) ? ~0x20 : ~0x40; + if (data->fan_min[n] == 0) + data->alarm_mask &= (n == 0) ? ~0x20 : ~0x40; else - data->alarm_mask |= (n == 1) ? 0x20 : 0x40; + data->alarm_mask |= (n == 0) ? 0x20 : 0x40; data->beep_mask &= data->alarm_mask; gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); @@ -370,8 +338,12 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c return count; } -static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; unsigned long v = simple_strtoul(buf, NULL, 10); u8 r; @@ -386,133 +358,282 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c } mutex_lock(&data->update_lock); - data->fan_div[n - 1] = r; + data->fan_div[n] = r; - if (n == 1) - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xc0) | (r << 6)); + if (n == 0) + gl520_write_value(client, GL520_REG_FAN_DIV, + (gl520_read_value(client, GL520_REG_FAN_DIV) + & ~0xc0) | (r << 6)); else - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4)); + gl520_write_value(client, GL520_REG_FAN_DIV, + (gl520_read_value(client, GL520_REG_FAN_DIV) + & ~0x30) | (r << 4)); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); u8 r = simple_strtoul(buf, NULL, 10)?1:0; mutex_lock(&data->update_lock); data->fan_off = r; - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2)); + gl520_write_value(client, GL520_REG_FAN_OFF, + (gl520_read_value(client, GL520_REG_FAN_OFF) + & ~0x0c) | (r << 2)); mutex_unlock(&data->update_lock); return count; } +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_input, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan_input, NULL, 1); +static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, + get_fan_min, set_fan_min, 0); +static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, + get_fan_min, set_fan_min, 1); +static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, + get_fan_div, set_fan_div, 0); +static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, + get_fan_div, set_fan_div, 1); +static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR, + get_fan_off, set_fan_off); + #define TEMP_FROM_REG(val) (((val) - 130) * 1000) #define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-500:(val)+500) / 1000)+130),0,255)) -static ssize_t get_temp_input(struct gl520_data *data, char *buf, int n) +static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n])); } -static ssize_t get_temp_max(struct gl520_data *data, char *buf, int n) +static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n])); } -static ssize_t get_temp_max_hyst(struct gl520_data *data, char *buf, int n) +static ssize_t get_temp_max_hyst(struct device *dev, struct device_attribute + *attr, char *buf) { - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n - 1])); + int n = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n])); } -static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); - data->temp_max[n - 1] = TEMP_TO_REG(v); - gl520_write_value(client, reg, data->temp_max[n - 1]); + data->temp_max[n] = TEMP_TO_REG(v); + gl520_write_value(client, GL520_REG_TEMP_MAX[n], data->temp_max[n]); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int n = to_sensor_dev_attr(attr)->index; long v = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); - data->temp_max_hyst[n - 1] = TEMP_TO_REG(v); - gl520_write_value(client, reg, data->temp_max_hyst[n - 1]); + data->temp_max_hyst[n] = TEMP_TO_REG(v); + gl520_write_value(client, GL520_REG_TEMP_MAX_HYST[n], + data->temp_max_hyst[n]); mutex_unlock(&data->update_lock); return count; } -static ssize_t get_alarms(struct gl520_data *data, char *buf, int n) +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_temp_input, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_temp_input, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, + get_temp_max, set_temp_max, 0); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, + get_temp_max, set_temp_max, 1); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, + get_temp_max_hyst, set_temp_max_hyst, 0); +static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, + get_temp_max_hyst, set_temp_max_hyst, 1); + +static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->alarms); } -static ssize_t get_beep_enable(struct gl520_data *data, char *buf, int n) +static ssize_t get_beep_enable(struct device *dev, struct device_attribute + *attr, char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->beep_enable); } -static ssize_t get_beep_mask(struct gl520_data *data, char *buf, int n) +static ssize_t get_beep_mask(struct device *dev, struct device_attribute *attr, + char *buf) { + struct gl520_data *data = gl520_update_device(dev); return sprintf(buf, "%d\n", data->beep_mask); } -static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_beep_enable(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); u8 r = simple_strtoul(buf, NULL, 10)?0:1; mutex_lock(&data->update_lock); data->beep_enable = !r; - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2)); + gl520_write_value(client, GL520_REG_BEEP_ENABLE, + (gl520_read_value(client, GL520_REG_BEEP_ENABLE) + & ~0x04) | (r << 2)); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg) +static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); u8 r = simple_strtoul(buf, NULL, 10); - + mutex_lock(&data->update_lock); r &= data->alarm_mask; data->beep_mask = r; - gl520_write_value(client, reg, r); + gl520_write_value(client, GL520_REG_BEEP_MASK, r); + mutex_unlock(&data->update_lock); + return count; +} + +static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); +static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, + get_beep_enable, set_beep_enable); +static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, + get_beep_mask, set_beep_mask); + +static ssize_t get_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bit_nr = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", (data->alarms >> bit_nr) & 1); +} + +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, get_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, get_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, get_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, get_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, get_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, get_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, get_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, get_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, get_alarm, NULL, 7); + +static ssize_t get_beep(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int bitnr = to_sensor_dev_attr(attr)->index; + struct gl520_data *data = gl520_update_device(dev); + + return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1); +} + +static ssize_t set_beep(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct gl520_data *data = i2c_get_clientdata(client); + int bitnr = to_sensor_dev_attr(attr)->index; + unsigned long bit; + + bit = simple_strtoul(buf, NULL, 10); + if (bit & ~1) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); + if (bit) + data->beep_mask |= (1 << bitnr); + else + data->beep_mask &= ~(1 << bitnr); + gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); mutex_unlock(&data->update_lock); return count; } +static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 0); +static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 1); +static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 2); +static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 3); +static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 4); +static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 5); +static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 6); +static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); +static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); + static struct attribute *gl520_attributes[] = { &dev_attr_cpu0_vid.attr, - &dev_attr_in0_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_input.attr, - &dev_attr_in1_min.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_input.attr, - &dev_attr_in2_min.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_input.attr, - &dev_attr_in3_min.attr, - &dev_attr_in3_max.attr, - - &dev_attr_fan1_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan1_div.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in0_beep.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in1_beep.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in2_beep.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in3_beep.dev_attr.attr, + + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_beep.dev_attr.attr, &dev_attr_fan1_off.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan2_div.attr, - - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_beep.dev_attr.attr, + + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_beep.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_beep_enable.attr, @@ -525,13 +646,17 @@ static const struct attribute_group gl520_group = { }; static struct attribute *gl520_attributes_opt[] = { - &dev_attr_in4_input.attr, - &dev_attr_in4_min.attr, - &dev_attr_in4_max.attr, - - &dev_attr_temp2_input.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp2_max_hyst.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in4_beep.dev_attr.attr, + + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_beep.dev_attr.attr, NULL }; @@ -553,7 +678,7 @@ static int gl520_attach_adapter(struct i2c_adapter *adapter) static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *new_client; + struct i2c_client *client; struct gl520_data *data; int err = 0; @@ -570,59 +695,65 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &gl520_driver; - new_client->flags = 0; + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &gl520_driver; /* Determine the chip type. */ if (kind < 0) { - if ((gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) || - ((gl520_read_value(new_client, GL520_REG_REVISION) & 0x7f) != 0x00) || - ((gl520_read_value(new_client, GL520_REG_CONF) & 0x80) != 0x00)) { - dev_dbg(&new_client->dev, "Unknown chip type, skipping\n"); + if ((gl520_read_value(client, GL520_REG_CHIP_ID) != 0x20) || + ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || + ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { + dev_dbg(&client->dev, "Unknown chip type, skipping\n"); goto exit_free; } } /* Fill in the remaining client fields */ - strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE); - data->valid = 0; + strlcpy(client->name, "gl520sm", I2C_NAME_SIZE); mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto exit_free; /* Initialize the GL520SM chip */ - gl520_init_client(new_client); + gl520_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &gl520_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group))) goto exit_detach; if (data->two_temps) { - if ((err = device_create_file(&new_client->dev, - &dev_attr_temp2_input)) - || (err = device_create_file(&new_client->dev, - &dev_attr_temp2_max)) - || (err = device_create_file(&new_client->dev, - &dev_attr_temp2_max_hyst))) + if ((err = device_create_file(&client->dev, + &sensor_dev_attr_temp2_input.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_temp2_max.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_temp2_max_hyst.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_temp2_alarm.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_temp2_beep.dev_attr))) goto exit_remove_files; } else { - if ((err = device_create_file(&new_client->dev, - &dev_attr_in4_input)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in4_min)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in4_max))) + if ((err = device_create_file(&client->dev, + &sensor_dev_attr_in4_input.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_in4_min.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_in4_max.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_in4_alarm.dev_attr)) + || (err = device_create_file(&client->dev, + &sensor_dev_attr_in4_beep.dev_attr))) goto exit_remove_files; } - data->hwmon_dev = hwmon_device_register(&new_client->dev); + data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; @@ -631,10 +762,10 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &gl520_group); - sysfs_remove_group(&new_client->dev.kobj, &gl520_group_opt); + sysfs_remove_group(&client->dev.kobj, &gl520_group); + sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); exit_detach: - i2c_detach_client(new_client); + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -697,7 +828,7 @@ static int gl520_detach_client(struct i2c_client *client) } -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized GL520 uses a high-byte first convention */ static int gl520_read_value(struct i2c_client *client, u8 reg) { @@ -720,7 +851,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct gl520_data *data = i2c_get_clientdata(client); - int val; + int val, i; mutex_lock(&data->update_lock); @@ -732,18 +863,13 @@ static struct gl520_data *gl520_update_device(struct device *dev) data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); data->vid = gl520_read_value(client, GL520_REG_VID_INPUT) & 0x1f; - val = gl520_read_value(client, GL520_REG_IN0_LIMIT); - data->in_min[0] = val & 0xff; - data->in_max[0] = (val >> 8) & 0xff; - val = gl520_read_value(client, GL520_REG_IN1_LIMIT); - data->in_min[1] = val & 0xff; - data->in_max[1] = (val >> 8) & 0xff; - val = gl520_read_value(client, GL520_REG_IN2_LIMIT); - data->in_min[2] = val & 0xff; - data->in_max[2] = (val >> 8) & 0xff; - val = gl520_read_value(client, GL520_REG_IN3_LIMIT); - data->in_min[3] = val & 0xff; - data->in_max[3] = (val >> 8) & 0xff; + for (i = 0; i < 4; i++) { + data->in_input[i] = gl520_read_value(client, + GL520_REG_IN_INPUT[i]); + val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]); + data->in_min[i] = val & 0xff; + data->in_max[i] = (val >> 8) & 0xff; + } val = gl520_read_value(client, GL520_REG_FAN_INPUT); data->fan_input[0] = (val >> 8) & 0xff; @@ -753,9 +879,12 @@ static struct gl520_data *gl520_update_device(struct device *dev) data->fan_min[0] = (val >> 8) & 0xff; data->fan_min[1] = val & 0xff; - data->temp_input[0] = gl520_read_value(client, GL520_REG_TEMP1_INPUT); - data->temp_max[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX); - data->temp_max_hyst[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX_HYST); + data->temp_input[0] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[0]); + data->temp_max[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX[0]); + data->temp_max_hyst[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[0]); val = gl520_read_value(client, GL520_REG_FAN_DIV); data->fan_div[0] = (val >> 6) & 0x03; @@ -767,20 +896,21 @@ static struct gl520_data *gl520_update_device(struct device *dev) val = gl520_read_value(client, GL520_REG_CONF); data->beep_enable = !((val >> 2) & 1); - data->in_input[0] = gl520_read_value(client, GL520_REG_IN0_INPUT); - data->in_input[1] = gl520_read_value(client, GL520_REG_IN1_INPUT); - data->in_input[2] = gl520_read_value(client, GL520_REG_IN2_INPUT); - data->in_input[3] = gl520_read_value(client, GL520_REG_IN3_INPUT); - /* Temp1 and Vin4 are the same input */ if (data->two_temps) { - data->temp_input[1] = gl520_read_value(client, GL520_REG_TEMP2_INPUT); - data->temp_max[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX); - data->temp_max_hyst[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX_HYST); + data->temp_input[1] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[1]); + data->temp_max[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX[1]); + data->temp_max_hyst[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[1]); } else { - data->in_input[4] = gl520_read_value(client, GL520_REG_IN4_INPUT); - data->in_min[4] = gl520_read_value(client, GL520_REG_IN4_MIN); - data->in_max[4] = gl520_read_value(client, GL520_REG_IN4_MAX); + data->in_input[4] = gl520_read_value(client, + GL520_REG_IN_INPUT[4]); + data->in_min[4] = gl520_read_value(client, + GL520_REG_IN_MIN[4]); + data->in_max[4] = gl520_read_value(client, + GL520_REG_IN_MAX[4]); } data->last_updated = jiffies; |