#include <linux/mutex.h>
/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
#define EMC6D102_REG_EXTEND_ADC3 0x87
#define EMC6D102_REG_EXTEND_ADC4 0x88
-#define LM85_ALARM_IN0 0x0001
-#define LM85_ALARM_IN1 0x0002
-#define LM85_ALARM_IN2 0x0004
-#define LM85_ALARM_IN3 0x0008
-#define LM85_ALARM_TEMP1 0x0010
-#define LM85_ALARM_TEMP2 0x0020
-#define LM85_ALARM_TEMP3 0x0040
-#define LM85_ALARM_ALARM2 0x0080
-#define LM85_ALARM_IN4 0x0100
-#define LM85_ALARM_RESERVED 0x0200
-#define LM85_ALARM_FAN1 0x0400
-#define LM85_ALARM_FAN2 0x0800
-#define LM85_ALARM_FAN3 0x1000
-#define LM85_ALARM_FAN4 0x2000
-#define LM85_ALARM_TEMP1_FAULT 0x4000
-#define LM85_ALARM_TEMP3_FAULT 0x8000
-
/* Conversions. Rounding and limit checking is only done on the TO_REG
variants. Note that you should be a bit careful with which arguments
#define INS_TO_REG(n,val) \
SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255)
-#define INSEXT_FROM_REG(n,val,ext,scale) \
- SCALE((val)*(scale) + (ext),192*(scale),lm85_scaling[n])
+#define INSEXT_FROM_REG(n,val,ext) \
+ SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n])
-#define INS_FROM_REG(n,val) INSEXT_FROM_REG(n,val,0,1)
+#define INS_FROM_REG(n,val) SCALE((val), 192, lm85_scaling[n])
/* FAN speed is measured using 90kHz clock */
-#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
+static inline u16 FAN_TO_REG(unsigned long val)
+{
+ if (!val)
+ return 0xffff;
+ return SENSORS_LIMIT(5400000 / val, 1, 0xfffe);
+}
#define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val))
/* Temperature is reported in .001 degC increments */
#define TEMP_TO_REG(val) \
SENSORS_LIMIT(SCALE(val,1000,1),-127,127)
-#define TEMPEXT_FROM_REG(val,ext,scale) \
- SCALE((val)*scale + (ext),scale,1000)
-#define TEMP_FROM_REG(val) \
- TEMPEXT_FROM_REG(val,0,1)
+#define TEMPEXT_FROM_REG(val,ext) \
+ SCALE(((val) << 4) + (ext), 16, 1000)
+#define TEMP_FROM_REG(val) ((val) * 1000)
#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
#define PWM_FROM_REG(val) (val)
u8 tach_mode; /* Register encoding, combined */
u8 temp_ext[3]; /* Decoded values */
u8 in_ext[8]; /* Decoded values */
- u8 adc_scale; /* ADC Extended bits scaling factor */
u8 fan_ppr; /* Register value */
u8 smooth[3]; /* Register encoding */
u8 vid; /* Register value */
.driver = {
.name = "lm85",
},
- .id = I2C_DRIVERID_LM85,
.attach_adapter = lm85_attach_adapter,
.detach_client = lm85_detach_client,
};
int nr = to_sensor_dev_attr(attr)->index;
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val);
static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct lm85_data *data = lm85_update_device(dev);
+ struct lm85_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
- u32 val;
-
- val = simple_strtoul(buf, NULL, 10);
- data->vrm = val;
+ struct lm85_data *data = dev_get_drvdata(dev);
+ data->vrm = simple_strtoul(buf, NULL, 10);
return count;
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct lm85_data *data = lm85_update_device(dev);
+ return sprintf(buf, "%u\n", (data->alarms >> nr) & 1);
+}
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 18);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 16);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 17);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 14);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 13);
+
/* pwm */
static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
{
int nr = to_sensor_dev_attr(attr)->index;
struct lm85_data *data = lm85_update_device(dev);
- int pwm_zone;
+ int pwm_zone, enable;
pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
- return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
+ switch (pwm_zone) {
+ case -1: /* PWM is always at 100% */
+ enable = 0;
+ break;
+ case 0: /* PWM is always at 0% */
+ case -2: /* PWM responds to manual control */
+ enable = 1;
+ break;
+ default: /* PWM in automatic mode */
+ enable = 2;
+ }
+ return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
+ *attr, const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ u8 config;
+
+ switch (val) {
+ case 0:
+ config = 3;
+ break;
+ case 1:
+ config = 7;
+ break;
+ case 2:
+ /* Here we have to choose arbitrarily one of the 5 possible
+ configurations; I go for the safest */
+ config = 6;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->update_lock);
+ data->autofan[nr].config = lm85_read_value(client,
+ LM85_REG_AFAN_CONFIG(nr));
+ data->autofan[nr].config = (data->autofan[nr].config & ~0xe0)
+ | (config << 5);
+ lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr),
+ data->autofan[nr].config);
+ mutex_unlock(&data->update_lock);
+ return count;
}
#define show_pwm_reg(offset) \
static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
show_pwm, set_pwm, offset - 1); \
-static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO, \
- show_pwm_enable, NULL, offset - 1)
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
+ show_pwm_enable, set_pwm_enable, offset - 1)
show_pwm_reg(1);
show_pwm_reg(2);
struct lm85_data *data = lm85_update_device(dev);
return sprintf( buf, "%d\n", INSEXT_FROM_REG(nr,
data->in[nr],
- data->in_ext[nr],
- data->adc_scale) );
+ data->in_ext[nr]));
}
static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
show_in_reg(2);
show_in_reg(3);
show_in_reg(4);
+show_in_reg(5);
+show_in_reg(6);
+show_in_reg(7);
/* Temps */
int nr = to_sensor_dev_attr(attr)->index;
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", TEMPEXT_FROM_REG(data->temp[nr],
- data->temp_ext[nr],
- data->adc_scale) );
+ data->temp_ext[nr]));
}
static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
&sensor_dev_attr_fan2_min.dev_attr.attr,
&sensor_dev_attr_fan3_min.dev_attr.attr,
&sensor_dev_attr_fan4_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan4_alarm.dev_attr.attr,
&sensor_dev_attr_pwm1.dev_attr.attr,
&sensor_dev_attr_pwm2.dev_attr.attr,
&sensor_dev_attr_in1_max.dev_attr.attr,
&sensor_dev_attr_in2_max.dev_attr.attr,
&sensor_dev_attr_in3_max.dev_attr.attr,
+ &sensor_dev_attr_in0_alarm.dev_attr.attr,
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
+ &sensor_dev_attr_in3_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp2_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp3_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_fault.dev_attr.attr,
+ &sensor_dev_attr_temp3_fault.dev_attr.attr,
&sensor_dev_attr_pwm1_auto_channels.dev_attr.attr,
&sensor_dev_attr_pwm2_auto_channels.dev_attr.attr,
.attrs = lm85_attributes,
};
-static struct attribute *lm85_attributes_opt[] = {
+static struct attribute *lm85_attributes_in4[] = {
&sensor_dev_attr_in4_input.dev_attr.attr,
&sensor_dev_attr_in4_min.dev_attr.attr,
&sensor_dev_attr_in4_max.dev_attr.attr,
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
NULL
};
-static const struct attribute_group lm85_group_opt = {
- .attrs = lm85_attributes_opt,
+static const struct attribute_group lm85_group_in4 = {
+ .attrs = lm85_attributes_in4,
+};
+
+static struct attribute *lm85_attributes_in567[] = {
+ &sensor_dev_attr_in5_input.dev_attr.attr,
+ &sensor_dev_attr_in6_input.dev_attr.attr,
+ &sensor_dev_attr_in7_input.dev_attr.attr,
+ &sensor_dev_attr_in5_min.dev_attr.attr,
+ &sensor_dev_attr_in6_min.dev_attr.attr,
+ &sensor_dev_attr_in7_min.dev_attr.attr,
+ &sensor_dev_attr_in5_max.dev_attr.attr,
+ &sensor_dev_attr_in6_max.dev_attr.attr,
+ &sensor_dev_attr_in7_max.dev_attr.attr,
+ &sensor_dev_attr_in5_alarm.dev_attr.attr,
+ &sensor_dev_attr_in6_alarm.dev_attr.attr,
+ &sensor_dev_attr_in7_alarm.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group lm85_group_in567 = {
+ .attrs = lm85_attributes_in567,
};
static int lm85_detect(struct i2c_adapter *adapter, int address,
as a sixth digital VID input rather than an analog input. */
data->vid = lm85_read_value(new_client, LM85_REG_VID);
if (!(kind == adt7463 && (data->vid & 0x80)))
- if ((err = device_create_file(&new_client->dev,
- &sensor_dev_attr_in4_input.dev_attr))
- || (err = device_create_file(&new_client->dev,
- &sensor_dev_attr_in4_min.dev_attr))
- || (err = device_create_file(&new_client->dev,
- &sensor_dev_attr_in4_max.dev_attr)))
+ if ((err = sysfs_create_group(&new_client->dev.kobj,
+ &lm85_group_in4)))
+ goto ERROR3;
+
+ /* The EMC6D100 has 3 additional voltage inputs */
+ if (kind == emc6d100)
+ if ((err = sysfs_create_group(&new_client->dev.kobj,
+ &lm85_group_in567)))
goto ERROR3;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
/* Error out and cleanup code */
ERROR3:
sysfs_remove_group(&new_client->dev.kobj, &lm85_group);
- sysfs_remove_group(&new_client->dev.kobj, &lm85_group_opt);
+ sysfs_remove_group(&new_client->dev.kobj, &lm85_group_in4);
+ if (kind == emc6d100)
+ sysfs_remove_group(&new_client->dev.kobj, &lm85_group_in567);
ERROR2:
i2c_detach_client(new_client);
ERROR1:
struct lm85_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm85_group);
- sysfs_remove_group(&client->dev.kobj, &lm85_group_opt);
+ sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
+ if (data->type == emc6d100)
+ sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
i2c_detach_client(client);
kfree(data);
return 0;
/* Have to read extended bits first to "freeze" the
* more significant bits that are read later.
+ * There are 2 additional resolution bits per channel and we
+ * have room for 4, so we shift them to the left.
*/
if ( (data->type == adm1027) || (data->type == adt7463) ) {
int ext1 = lm85_read_value(client,
int val = (ext1 << 8) + ext2;
for(i = 0; i <= 4; i++)
- data->in_ext[i] = (val>>(i * 2))&0x03;
+ data->in_ext[i] = ((val>>(i * 2))&0x03) << 2;
for(i = 0; i <= 2; i++)
- data->temp_ext[i] = (val>>((i + 5) * 2))&0x03;
+ data->temp_ext[i] = (val>>((i + 4) * 2))&0x0c;
}
- /* adc_scale is 2^(number of LSBs). There are 4 extra bits in
- the emc6d102 and 2 in the adt7463 and adm1027. In all
- other chips ext is always 0 and the value of scale is
- irrelevant. So it is left in 4*/
- data->adc_scale = (data->type == emc6d102 ) ? 16 : 4;
-
data->vid = lm85_read_value(client, LM85_REG_VID);
for (i = 0; i <= 3; ++i) {