Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 294834
b: refs/heads/master
c: 817c6cc
h: refs/heads/master
v: v3
  • Loading branch information
Jean Delvare authored and Jean Delvare committed Mar 23, 2012
1 parent edbe447 commit e7af56e
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dac27dce318401fee028b19cdd4c52fe163f53f1
refs/heads/master: 817c6cc546a4ebea8016766f0f26e7d53118c6b6
105 changes: 89 additions & 16 deletions trunk/drivers/hwmon/lm63.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,36 @@ static inline int lut_temp_from_reg(struct lm63_data *data, int nr)
return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000);
}

/*
* Update the lookup table register cache.
* client->update_lock must be held when calling this function.
*/
static void lm63_update_lut(struct i2c_client *client)
{
struct lm63_data *data = i2c_get_clientdata(client);
int i;

if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
!data->lut_valid) {
for (i = 0; i < data->lut_size; i++) {
data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
LM63_REG_LUT_PWM(i));
data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
LM63_REG_LUT_TEMP(i));
}
data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
LM63_REG_LUT_TEMP_HYST);

data->lut_last_updated = jiffies;
data->lut_valid = 1;
}
}

static struct lm63_data *lm63_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
unsigned long next_update;
int i;

mutex_lock(&data->update_lock);

Expand Down Expand Up @@ -278,26 +302,39 @@ static struct lm63_data *lm63_update_device(struct device *dev)
data->valid = 1;
}

if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
!data->lut_valid) {
for (i = 0; i < data->lut_size; i++) {
data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
LM63_REG_LUT_PWM(i));
data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
LM63_REG_LUT_TEMP(i));
}
data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
LM63_REG_LUT_TEMP_HYST);

data->lut_last_updated = jiffies;
data->lut_valid = 1;
}
lm63_update_lut(client);

mutex_unlock(&data->update_lock);

return data;
}

/*
* Trip points in the lookup table should be in ascending order for both
* temperatures and PWM output values.
*/
static int lm63_lut_looks_bad(struct i2c_client *client)
{
struct lm63_data *data = i2c_get_clientdata(client);
int i;

mutex_lock(&data->update_lock);
lm63_update_lut(client);

for (i = 1; i < data->lut_size; i++) {
if (data->pwm1[1 + i - 1] > data->pwm1[1 + i]
|| data->temp8[3 + i - 1] > data->temp8[3 + i]) {
dev_warn(&client->dev,
"Lookup table doesn't look sane (check entries %d and %d)\n",
i, i + 1);
break;
}
}
mutex_unlock(&data->update_lock);

return i == data->lut_size ? 0 : 1;
}

/*
* Sysfs callback functions and files
*/
Expand Down Expand Up @@ -381,6 +418,41 @@ static ssize_t show_pwm1_enable(struct device *dev,
return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
}

static ssize_t set_pwm1_enable(struct device *dev,
struct device_attribute *dummy,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
unsigned long val;
int err;

err = kstrtoul(buf, 10, &val);
if (err)
return err;
if (val < 1 || val > 2)
return -EINVAL;

/*
* Only let the user switch to automatic mode if the lookup table
* looks sane.
*/
if (val == 2 && lm63_lut_looks_bad(client))
return -EPERM;

mutex_lock(&data->update_lock);
data->config_fan = i2c_smbus_read_byte_data(client,
LM63_REG_CONFIG_FAN);
if (val == 1)
data->config_fan |= 0x20;
else
data->config_fan &= ~0x20;
i2c_smbus_write_byte_data(client, LM63_REG_CONFIG_FAN,
data->config_fan);
mutex_unlock(&data->update_lock);
return count;
}

/*
* There are 8bit registers for both local(temp1) and remote(temp2) sensor.
* For remote sensor registers temp2_offset has to be considered,
Expand Down Expand Up @@ -669,7 +741,8 @@ static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
set_fan, 1);

static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0);
static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
show_pwm1_enable, set_pwm1_enable);
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1);
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO,
show_lut_temp, NULL, 3);
Expand Down

0 comments on commit e7af56e

Please sign in to comment.