* w83795.c - Linux kernel driver for hardware monitoring
* Copyright (C) 2008 Nuvoton Technology Corp.
* Wei Song
+ * Copyright (C) 2010 Jean Delvare <khali@linux-fr.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#define W83795_REG_FANIN_CTRL2 0x07
#define W83795_REG_VMIGB_CTRL 0x08
-#define TEMP_CTRL_DISABLE 0
-#define TEMP_CTRL_TD 1
-#define TEMP_CTRL_VSEN 2
-#define TEMP_CTRL_TR 3
-#define TEMP_CTRL_SHIFT 4
-#define TEMP_CTRL_HASIN_SHIFT 5
-/* temp mode may effect VSEN17-12 (in20-15) */
-static const u16 W83795_REG_TEMP_CTRL[][6] = {
- /* Disable, TD, VSEN, TR, register shift value, has_in shift num */
- {0x00, 0x01, 0x02, 0x03, 0, 17}, /* TR1 */
- {0x00, 0x04, 0x08, 0x0C, 2, 18}, /* TR2 */
- {0x00, 0x10, 0x20, 0x30, 4, 19}, /* TR3 */
- {0x00, 0x40, 0x80, 0xC0, 6, 20}, /* TR4 */
- {0x00, 0x00, 0x02, 0x03, 0, 15}, /* TR5 */
- {0x00, 0x00, 0x08, 0x0C, 2, 16}, /* TR6 */
-};
-
#define TEMP_READ 0
#define TEMP_CRIT 1
#define TEMP_CRIT_HYST 2
{0x24, 0xa2, 0xa3}, /* VSEN17 */
};
#define W83795_REG_VRLSB 0x3C
-#define VRLSB_SHIFT 6
static const u8 W83795_REG_IN_HL_LSB[] = {
0x8e, /* VSEN1-4 */
(((type) == 1) ? W83795_REG_IN_HL_LSB[(index)] \
: (W83795_REG_IN_HL_LSB[(index)] + 1))
-#define IN_LSB_REG_NUM 10
-
#define IN_LSB_SHIFT 0
#define IN_LSB_IDX 1
static const u8 IN_LSB_SHIFT_IDX[][2] = {
};
-/* 3VDD, 3VSB, VBAT * 0.006 */
-#define REST_VLT_BEGIN 12 /* the 13th volt to 15th */
-#define REST_VLT_END 14 /* the 13th volt to 15th */
-
#define W83795_REG_FAN(index) (0x2E + (index))
#define W83795_REG_FAN_MIN_HL(index) (0xB6 + (index))
#define W83795_REG_FAN_MIN_LSB(index) (0xC4 + (index) / 2)
#define W83795_REG_FAN_MIN_LSB_SHIFT(index) \
- (((index) % 1) ? 4 : 0)
+ (((index) & 1) ? 4 : 0)
#define W83795_REG_VID_CTRL 0x6A
-#define ALARM_BEEP_REG_NUM 6
#define W83795_REG_ALARM(index) (0x41 + (index))
#define W83795_REG_BEEP(index) (0x50 + (index))
#define W83795_REG_CLR_CHASSIS 0x4D
-#define W83795_REG_TEMP_NUM 6
#define W83795_REG_FCMS1 0x201
#define W83795_REG_FCMS2 0x208
#define W83795_REG_TFMR(index) (0x202 + (index))
#define W83795_REG_TSS(index) (0x209 + (index))
#define PWM_OUTPUT 0
-#define PWM_START 1
-#define PWM_NONSTOP 2
-#define PWM_STOP_TIME 3
-#define PWM_FREQ 4
-#define W83795_REG_PWM(index, nr) \
- (((nr) == 0 ? 0x210 : \
- (nr) == 1 ? 0x220 : \
- (nr) == 2 ? 0x228 : \
- (nr) == 3 ? 0x230 : 0x218) + (index))
+#define PWM_FREQ 1
+#define PWM_START 2
+#define PWM_NONSTOP 3
+#define PWM_STOP_TIME 4
+#define W83795_REG_PWM(index, nr) (0x210 + (nr) * 8 + (index))
#define W83795_REG_FTSH(index) (0x240 + (index) * 2)
#define W83795_REG_FTSL(index) (0x241 + (index) * 2)
static inline u16 in_from_reg(u8 index, u16 val)
{
- if ((index >= REST_VLT_BEGIN) && (index <= REST_VLT_END))
+ /* 3VDD, 3VSB and VBAT: 6 mV/bit; other inputs: 2 mV/bit */
+ if (index >= 12 && index <= 14)
return val * 6;
else
return val * 2;
static inline u16 in_to_reg(u8 index, u16 val)
{
- if ((index >= REST_VLT_BEGIN) && (index <= REST_VLT_END))
+ if (index >= 12 && index <= 14)
return val / 6;
else
return val / 2;
u8 has_temp; /* Enable monitor temp6-1 or not */
s8 temp[6][5]; /* current, crit, crit_hyst, warn, warn_hyst */
u8 temp_read_vrlsb[6];
- u8 temp_mode; /* bit 0: TR mode, bit 1: TD mode */
+ u8 temp_mode; /* Bit vector, 0 = TR, 1 = TD */
u8 temp_src[3]; /* Register value */
u8 enable_dts; /* Enable PECI and SB-TSI,
u8 has_pwm; /* 795g supports 8 pwm, 795adg only supports 2,
* no config register, only affected by chip
* type */
- u8 pwm[8][5]; /* Register value, output, start, non stop, stop
- * time, freq */
+ u8 pwm[8][5]; /* Register value, output, freq, start,
+ * non stop, stop time */
u16 clkin; /* CLKIN frequency in kHz */
u8 pwm_fcms[2]; /* Register value */
u8 pwm_tfmr[6]; /* Register value */
u8 beeps[6]; /* Register value */
char valid;
+ char valid_limits;
+ char valid_pwm_config;
};
/*
return err;
}
+static void w83795_update_limits(struct i2c_client *client)
+{
+ struct w83795_data *data = i2c_get_clientdata(client);
+ int i, limit;
+
+ /* Read the voltage limits */
+ for (i = 0; i < ARRAY_SIZE(data->in); i++) {
+ if (!(data->has_in & (1 << i)))
+ continue;
+ data->in[i][IN_MAX] =
+ w83795_read(client, W83795_REG_IN[i][IN_MAX]);
+ data->in[i][IN_LOW] =
+ w83795_read(client, W83795_REG_IN[i][IN_LOW]);
+ }
+ for (i = 0; i < ARRAY_SIZE(data->in_lsb); i++) {
+ if ((i == 2 && data->chip_type == w83795adg) ||
+ (i >= 4 && !(data->has_in & (1 << (i + 11)))))
+ continue;
+ data->in_lsb[i][IN_MAX] =
+ w83795_read(client, IN_LSB_REG(i, IN_MAX));
+ data->in_lsb[i][IN_LOW] =
+ w83795_read(client, IN_LSB_REG(i, IN_LOW));
+ }
+
+ /* Read the fan limits */
+ for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
+ u8 lsb;
+
+ /* Each register contains LSB for 2 fans, but we want to
+ * read it only once to save time */
+ if ((i & 1) == 0 && (data->has_fan & (3 << i)))
+ lsb = w83795_read(client, W83795_REG_FAN_MIN_LSB(i));
+
+ if (!(data->has_fan & (1 << i)))
+ continue;
+ data->fan_min[i] =
+ w83795_read(client, W83795_REG_FAN_MIN_HL(i)) << 4;
+ data->fan_min[i] |=
+ (lsb >> W83795_REG_FAN_MIN_LSB_SHIFT(i)) & 0x0F;
+ }
+
+ /* Read the temperature limits */
+ for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+ if (!(data->has_temp & (1 << i)))
+ continue;
+ for (limit = TEMP_CRIT; limit <= TEMP_WARN_HYST; limit++)
+ data->temp[i][limit] =
+ w83795_read(client, W83795_REG_TEMP[i][limit]);
+ }
+
+ /* Read the DTS limits */
+ if (data->enable_dts) {
+ for (limit = DTS_CRIT; limit <= DTS_WARN_HYST; limit++)
+ data->dts_ext[limit] =
+ w83795_read(client, W83795_REG_DTS_EXT(limit));
+ }
+
+ /* Read beep settings */
+ for (i = 0; i < ARRAY_SIZE(data->beeps); i++)
+ data->beeps[i] = w83795_read(client, W83795_REG_BEEP(i));
+
+ data->valid_limits = 1;
+}
+
+static struct w83795_data *w83795_update_pwm_config(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83795_data *data = i2c_get_clientdata(client);
+ int i, tmp;
+
+ mutex_lock(&data->update_lock);
+
+ if (data->valid_pwm_config)
+ goto END;
+
+ /* Read temperature source selection */
+ for (i = 0; i < ARRAY_SIZE(data->temp_src); i++)
+ data->temp_src[i] = w83795_read(client, W83795_REG_TSS(i));
+
+ /* Read automatic fan speed control settings */
+ data->pwm_fcms[0] = w83795_read(client, W83795_REG_FCMS1);
+ data->pwm_fcms[1] = w83795_read(client, W83795_REG_FCMS2);
+ for (i = 0; i < ARRAY_SIZE(data->pwm_tfmr); i++)
+ data->pwm_tfmr[i] = w83795_read(client, W83795_REG_TFMR(i));
+ data->pwm_fomc = w83795_read(client, W83795_REG_FOMC);
+ for (i = 0; i < data->has_pwm; i++) {
+ for (tmp = PWM_FREQ; tmp <= PWM_STOP_TIME; tmp++)
+ data->pwm[i][tmp] =
+ w83795_read(client, W83795_REG_PWM(i, tmp));
+ }
+ for (i = 0; i < ARRAY_SIZE(data->target_speed); i++) {
+ data->target_speed[i] =
+ w83795_read(client, W83795_REG_FTSH(i)) << 4;
+ data->target_speed[i] |=
+ w83795_read(client, W83795_REG_FTSL(i)) >> 4;
+ }
+ data->tol_speed = w83795_read(client, W83795_REG_TFTS) & 0x3f;
+
+ for (i = 0; i < ARRAY_SIZE(data->pwm_temp); i++) {
+ data->pwm_temp[i][TEMP_PWM_TTTI] =
+ w83795_read(client, W83795_REG_TTTI(i)) & 0x7f;
+ data->pwm_temp[i][TEMP_PWM_CTFS] =
+ w83795_read(client, W83795_REG_CTFS(i));
+ tmp = w83795_read(client, W83795_REG_HT(i));
+ data->pwm_temp[i][TEMP_PWM_HCT] = tmp >> 4;
+ data->pwm_temp[i][TEMP_PWM_HOT] = tmp & 0x0f;
+ }
+
+ /* Read SmartFanIV trip points */
+ for (i = 0; i < ARRAY_SIZE(data->sf4_reg); i++) {
+ for (tmp = 0; tmp < 7; tmp++) {
+ data->sf4_reg[i][SF4_TEMP][tmp] =
+ w83795_read(client,
+ W83795_REG_SF4_TEMP(i, tmp));
+ data->sf4_reg[i][SF4_PWM][tmp] =
+ w83795_read(client, W83795_REG_SF4_PWM(i, tmp));
+ }
+ }
+
+ /* Read setup PWM */
+ for (i = 0; i < ARRAY_SIZE(data->setup_pwm); i++)
+ data->setup_pwm[i] =
+ w83795_read(client, W83795_REG_SETUP_PWM(i));
+
+ data->valid_pwm_config = 1;
+
+END:
+ mutex_unlock(&data->update_lock);
+ return data;
+}
+
static struct w83795_data *w83795_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
mutex_lock(&data->update_lock);
+ if (!data->valid_limits)
+ w83795_update_limits(client);
+
if (!(time_after(jiffies, data->last_updated + HZ * 2)
|| !data->valid))
goto END;
if (!(data->has_in & (1 << i)))
continue;
tmp = w83795_read(client, W83795_REG_IN[i][IN_READ]) << 2;
- tmp |= (w83795_read(client, W83795_REG_VRLSB)
- >> VRLSB_SHIFT) & 0x03;
+ tmp |= w83795_read(client, W83795_REG_VRLSB) >> 6;
data->in[i][IN_READ] = tmp;
}
if (!(data->has_fan & (1 << i)))
continue;
data->fan[i] = w83795_read(client, W83795_REG_FAN(i)) << 4;
- data->fan[i] |=
- (w83795_read(client, W83795_REG_VRLSB) >> 4) & 0x0F;
+ data->fan[i] |= w83795_read(client, W83795_REG_VRLSB) >> 4;
}
/* Update temperature */
for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
- /* even stop monitor, register still keep value, just read out
- * it */
- if (!(data->has_temp & (1 << i))) {
- data->temp[i][TEMP_READ] = 0;
- data->temp_read_vrlsb[i] = 0;
- continue;
- }
data->temp[i][TEMP_READ] =
w83795_read(client, W83795_REG_TEMP[i][TEMP_READ]);
data->temp_read_vrlsb[i] =
}
/* Update dts temperature */
- if (data->enable_dts != 0) {
+ if (data->enable_dts) {
for (i = 0; i < ARRAY_SIZE(data->dts); i++) {
if (!(data->has_dts & (1 << i)))
continue;
}
/* update alarm */
- for (i = 0; i < ALARM_BEEP_REG_NUM; i++)
+ for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i));
data->last_updated = jiffies;
int bit = sensor_attr->index & 0x07;
u8 val;
- if (ALARM_STATUS == nr) {
- val = (data->alarms[index] >> (bit)) & 1;
- } else { /* BEEP_ENABLE */
- val = (data->beeps[index] >> (bit)) & 1;
- }
+ if (nr == ALARM_STATUS)
+ val = (data->alarms[index] >> bit) & 1;
+ else /* BEEP_ENABLE */
+ val = (data->beeps[index] >> bit) & 1;
return sprintf(buf, "%u\n", val);
}
return count;
}
-/* Write any value to clear chassis alarm */
+/* Write 0 to clear chassis alarm */
static ssize_t
store_chassis_clear(struct device *dev,
struct device_attribute *attr, const char *buf,
{
struct i2c_client *client = to_i2c_client(dev);
struct w83795_data *data = i2c_get_clientdata(client);
- u8 val;
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val) < 0 || val != 0)
+ return -EINVAL;
mutex_lock(&data->update_lock);
val = w83795_read(client, W83795_REG_CLR_CHASSIS);
struct w83795_data *data = w83795_update_device(dev);
u16 val;
- if (FAN_INPUT == nr)
+ if (nr == FAN_INPUT)
val = data->fan[index] & 0x0fff;
else
val = data->fan_min[index] & 0x0fff;
data->fan_min[index] = val;
w83795_write(client, W83795_REG_FAN_MIN_HL(index), (val >> 4) & 0xff);
val &= 0x0f;
- if (index % 1) {
+ if (index & 1) {
val <<= 4;
val |= w83795_read(client, W83795_REG_FAN_MIN_LSB(index))
& 0x0f;
static ssize_t
show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w83795_data *data = w83795_update_device(dev);
+ struct w83795_data *data;
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
int index = sensor_attr->index;
unsigned int val;
+ data = nr == PWM_OUTPUT ? w83795_update_device(dev)
+ : w83795_update_pwm_config(dev);
+
switch (nr) {
case PWM_STOP_TIME:
val = time_from_reg(data->pwm[index][nr]);
{
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
int index = sensor_attr->index;
u8 tmp;
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int index = sensor_attr->index;
{
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
int index = sensor_attr->index;
u8 val = index / 2;
u8 tmp = data->temp_src[val];
- if (index % 1)
+ if (index & 1)
val = 4;
else
val = 0;
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int index = sensor_attr->index;
tmp = SENSORS_LIMIT(tmp, 0, 15);
mutex_lock(&data->update_lock);
- if (index % 1) {
+ if (index & 1) {
tmp <<= 4;
data->temp_src[val] &= 0x0f;
} else {
show_temp_pwm_enable(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
switch (nr) {
case TEMP_PWM_ENABLE:
- if ((tmp != 3) && (tmp != 4))
+ if (tmp != 3 && tmp != 4)
return -EINVAL;
tmp -= 3;
mutex_lock(&data->update_lock);
static ssize_t
show_fanin(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
switch (nr) {
case FANIN_TARGET:
val = fan_to_reg(SENSORS_LIMIT(val, 0, 0xfff));
- w83795_write(client, W83795_REG_FTSH(index), (val >> 4) & 0xff);
+ w83795_write(client, W83795_REG_FTSH(index), val >> 4);
w83795_write(client, W83795_REG_FTSL(index), (val << 4) & 0xf0);
data->target_speed[index] = val;
break;
static ssize_t
show_temp_pwm(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
static ssize_t
show_sf4_pwm(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
static ssize_t
show_sf4_temp(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
struct w83795_data *data = w83795_update_device(dev);
long temp = temp_from_reg(data->temp[index][nr]);
- if (TEMP_READ == nr)
- temp += ((data->temp_read_vrlsb[index] >> VRLSB_SHIFT) & 0x03)
- * 250;
+ if (nr == TEMP_READ)
+ temp += (data->temp_read_vrlsb[index] >> 6) * 250;
return sprintf(buf, "%ld\n", temp);
}
static ssize_t
show_dts_mode(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
- struct sensor_device_attribute_2 *sensor_attr =
- to_sensor_dev_attr_2(attr);
- int index = sensor_attr->index;
- u8 tmp;
-
- if (data->enable_dts == 0)
- return sprintf(buf, "%d\n", 0);
+ struct w83795_data *data = dev_get_drvdata(dev);
+ int tmp;
- if ((data->has_dts >> index) & 0x01) {
- if (data->enable_dts & 2)
- tmp = 5;
- else
- tmp = 6;
- } else {
- tmp = 0;
- }
+ if (data->enable_dts & 2)
+ tmp = 5;
+ else
+ tmp = 6;
return sprintf(buf, "%d\n", tmp);
}
struct w83795_data *data = w83795_update_device(dev);
long temp = temp_from_reg(data->dts[index]);
- temp += ((data->dts_read_vrlsb[index] >> VRLSB_SHIFT) & 0x03) * 250;
+ temp += (data->dts_read_vrlsb[index] >> 6) * 250;
return sprintf(buf, "%ld\n", temp);
}
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = dev_get_drvdata(dev);
long temp = temp_from_reg(data->dts_ext[nr]);
return sprintf(buf, "%ld\n", temp);
}
-/*
- Type 3: Thermal diode
- Type 4: Thermistor
-
- Temp5-6, default TR
- Temp1-4, default TD
-*/
-
static ssize_t
show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int index = sensor_attr->index;
- u8 tmp;
+ int tmp;
- if (data->has_temp >> index & 0x01) {
- if (data->temp_mode >> index & 0x01)
- tmp = 3;
- else
- tmp = 4;
- } else {
- tmp = 0;
- }
+ if (data->temp_mode & (1 << index))
+ tmp = 3; /* Thermal diode */
+ else
+ tmp = 4; /* Thermistor */
return sprintf(buf, "%d\n", tmp);
}
+/* Only for temp1-4 (temp5-6 can only be thermistor) */
static ssize_t
store_temp_mode(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int index = sensor_attr->index;
+ int reg_shift;
unsigned long val;
u8 tmp;
- u32 mask;
if (strict_strtoul(buf, 10, &val) < 0)
return -EINVAL;
if ((val != 4) && (val != 3))
return -EINVAL;
- if ((index > 3) && (val == 3))
- return -EINVAL;
mutex_lock(&data->update_lock);
if (val == 3) {
- val = TEMP_CTRL_TD;
- data->has_temp |= 1 << index;
+ /* Thermal diode */
+ val = 0x01;
data->temp_mode |= 1 << index;
} else if (val == 4) {
- val = TEMP_CTRL_TR;
- data->has_temp |= 1 << index;
- tmp = 1 << index;
- data->temp_mode &= ~tmp;
+ /* Thermistor */
+ val = 0x03;
+ data->temp_mode &= ~(1 << index);
}
- if (index > 3)
- tmp = w83795_read(client, W83795_REG_TEMP_CTRL1);
- else
- tmp = w83795_read(client, W83795_REG_TEMP_CTRL2);
-
- mask = 0x03 << W83795_REG_TEMP_CTRL[index][TEMP_CTRL_SHIFT];
- tmp &= ~mask;
- tmp |= W83795_REG_TEMP_CTRL[index][val];
-
- mask = 1 << W83795_REG_TEMP_CTRL[index][TEMP_CTRL_HASIN_SHIFT];
- data->has_in &= ~mask;
-
- if (index > 3)
- w83795_write(client, W83795_REG_TEMP_CTRL1, tmp);
- else
- w83795_write(client, W83795_REG_TEMP_CTRL2, tmp);
+ reg_shift = 2 * index;
+ tmp = w83795_read(client, W83795_REG_TEMP_CTRL2);
+ tmp &= ~(0x03 << reg_shift);
+ tmp |= val << reg_shift;
+ w83795_write(client, W83795_REG_TEMP_CTRL2, tmp);
mutex_unlock(&data->update_lock);
return count;
lsb_idx = IN_LSB_SHIFT_IDX[index][IN_LSB_IDX];
val <<= 2;
val |= (data->in_lsb[lsb_idx][nr] >>
- IN_LSB_SHIFT_IDX[lsb_idx][IN_LSB_SHIFT]) & 0x03;
+ IN_LSB_SHIFT_IDX[index][IN_LSB_SHIFT]) & 0x03;
if ((index >= 17) &&
!((data->has_gain >> (index - 17)) & 1))
val *= 8;
}
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
static ssize_t
show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute_2 *sensor_attr =
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83795_data *data = i2c_get_clientdata(client);
+ struct w83795_data *data = w83795_update_pwm_config(dev);
u16 val = data->setup_pwm[nr];
switch (nr) {
mutex_unlock(&data->update_lock);
return count;
}
+#endif
#define NOT_USED -1
show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) }
#define SENSOR_ATTR_TEMP(index) { \
- SENSOR_ATTR_2(temp##index##_type, S_IRUGO | S_IWUSR, \
+ SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
show_temp_mode, store_temp_mode, NOT_USED, index - 1), \
SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \
NULL, TEMP_READ, index - 1), \
};
static const struct sensor_device_attribute_2 sda_single_files[] = {
- SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
+ SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep,
store_chassis_clear, ALARM_STATUS, 46),
+ SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep,
+ store_beep, BEEP_ENABLE, 46),
SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep,
store_beep, BEEP_ENABLE, 47),
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin,
store_fanin, FANIN_TOL, NOT_USED),
SENSOR_ATTR_2(pwm_default, S_IWUSR | S_IRUGO, show_sf_setup,
store_sf_setup, SETUP_PWM_UPTIME, NOT_USED),
SENSOR_ATTR_2(pwm_downtime, S_IWUSR | S_IRUGO, show_sf_setup,
store_sf_setup, SETUP_PWM_DOWNTIME, NOT_USED),
+#endif
};
/*
return err;
}
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
for (i = 0; i < data->has_pwm; i++) {
for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) {
err = fn(dev, &w83795_pwm[i][j].dev_attr);
return err;
}
}
+#endif
for (i = 0; i < ARRAY_SIZE(w83795_temp); i++) {
if (!(data->has_temp & (1 << i)))
continue;
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
for (j = 0; j < ARRAY_SIZE(w83795_temp[0]); j++) {
+#else
+ for (j = 0; j < 8; j++) {
+#endif
err = fn(dev, &w83795_temp[i][j].dev_attr);
if (err)
return err;
}
}
- if (data->enable_dts != 0) {
+ if (data->enable_dts) {
for (i = 0; i < ARRAY_SIZE(w83795_dts); i++) {
if (!(data->has_dts & (1 << i)))
continue;
}
}
- /* First update the voltages measured value and limits */
- for (i = 0; i < ARRAY_SIZE(data->in); i++) {
- if (!(data->has_in & (1 << i)))
- continue;
- data->in[i][IN_MAX] =
- w83795_read(client, W83795_REG_IN[i][IN_MAX]);
- data->in[i][IN_LOW] =
- w83795_read(client, W83795_REG_IN[i][IN_LOW]);
- tmp = w83795_read(client, W83795_REG_IN[i][IN_READ]) << 2;
- tmp |= (w83795_read(client, W83795_REG_VRLSB)
- >> VRLSB_SHIFT) & 0x03;
- data->in[i][IN_READ] = tmp;
- }
- for (i = 0; i < IN_LSB_REG_NUM; i++) {
- if ((i == 2 && data->chip_type == w83795adg) ||
- (i >= 4 && !(data->has_in & (1 << (i + 11)))))
- continue;
- data->in_lsb[i][IN_MAX] =
- w83795_read(client, IN_LSB_REG(i, IN_MAX));
- data->in_lsb[i][IN_LOW] =
- w83795_read(client, IN_LSB_REG(i, IN_LOW));
- }
data->has_gain = w83795_read(client, W83795_REG_VMIGB_CTRL) & 0x0f;
- /* First update fan and limits */
- for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
- /* Each register contains LSB for 2 fans, but we want to
- * read it only once to save time */
- if ((i & 1) == 0 && (data->has_fan & (3 << i)))
- tmp = w83795_read(client, W83795_REG_FAN_MIN_LSB(i));
-
- if (!(data->has_fan & (1 << i)))
- continue;
- data->fan_min[i] =
- w83795_read(client, W83795_REG_FAN_MIN_HL(i)) << 4;
- data->fan_min[i] |=
- (tmp >> W83795_REG_FAN_MIN_LSB_SHIFT(i)) & 0x0F;
- data->fan[i] = w83795_read(client, W83795_REG_FAN(i)) << 4;
- data->fan[i] |=
- (w83795_read(client, W83795_REG_VRLSB) >> 4) & 0x0F;
- }
-
- /* temperature and limits */
- for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
- if (!(data->has_temp & (1 << i)))
- continue;
- data->temp[i][TEMP_CRIT] =
- w83795_read(client, W83795_REG_TEMP[i][TEMP_CRIT]);
- data->temp[i][TEMP_CRIT_HYST] =
- w83795_read(client, W83795_REG_TEMP[i][TEMP_CRIT_HYST]);
- data->temp[i][TEMP_WARN] =
- w83795_read(client, W83795_REG_TEMP[i][TEMP_WARN]);
- data->temp[i][TEMP_WARN_HYST] =
- w83795_read(client, W83795_REG_TEMP[i][TEMP_WARN_HYST]);
- data->temp[i][TEMP_READ] =
- w83795_read(client, W83795_REG_TEMP[i][TEMP_READ]);
- data->temp_read_vrlsb[i] =
- w83795_read(client, W83795_REG_VRLSB);
- }
-
- /* dts temperature and limits */
- if (data->enable_dts != 0) {
- data->dts_ext[DTS_CRIT] =
- w83795_read(client, W83795_REG_DTS_EXT(DTS_CRIT));
- data->dts_ext[DTS_CRIT_HYST] =
- w83795_read(client, W83795_REG_DTS_EXT(DTS_CRIT_HYST));
- data->dts_ext[DTS_WARN] =
- w83795_read(client, W83795_REG_DTS_EXT(DTS_WARN));
- data->dts_ext[DTS_WARN_HYST] =
- w83795_read(client, W83795_REG_DTS_EXT(DTS_WARN_HYST));
- for (i = 0; i < ARRAY_SIZE(data->dts); i++) {
- if (!(data->has_dts & (1 << i)))
- continue;
- data->dts[i] = w83795_read(client, W83795_REG_DTS(i));
- data->dts_read_vrlsb[i] =
- w83795_read(client, W83795_REG_VRLSB);
- }
- }
-
- /* First update temp source selction */
- for (i = 0; i < 3; i++)
- data->temp_src[i] = w83795_read(client, W83795_REG_TSS(i));
-
/* pwm and smart fan */
if (data->chip_type == w83795g)
data->has_pwm = 8;
else
data->has_pwm = 2;
- data->pwm_fcms[0] = w83795_read(client, W83795_REG_FCMS1);
- data->pwm_fcms[1] = w83795_read(client, W83795_REG_FCMS2);
- for (i = 0; i < W83795_REG_TEMP_NUM; i++)
- data->pwm_tfmr[i] = w83795_read(client, W83795_REG_TFMR(i));
- data->pwm_fomc = w83795_read(client, W83795_REG_FOMC);
- for (i = 0; i < data->has_pwm; i++) {
- for (tmp = 0; tmp < 5; tmp++) {
- data->pwm[i][tmp] =
- w83795_read(client, W83795_REG_PWM(i, tmp));
- }
- }
- for (i = 0; i < 8; i++) {
- data->target_speed[i] =
- w83795_read(client, W83795_REG_FTSH(i)) << 4;
- data->target_speed[i] |=
- w83795_read(client, W83795_REG_FTSL(i)) >> 4;
- }
- data->tol_speed = w83795_read(client, W83795_REG_TFTS) & 0x3f;
-
- for (i = 0; i < W83795_REG_TEMP_NUM; i++) {
- data->pwm_temp[i][TEMP_PWM_TTTI] =
- w83795_read(client, W83795_REG_TTTI(i)) & 0x7f;
- data->pwm_temp[i][TEMP_PWM_CTFS] =
- w83795_read(client, W83795_REG_CTFS(i));
- tmp = w83795_read(client, W83795_REG_HT(i));
- data->pwm_temp[i][TEMP_PWM_HCT] = (tmp >> 4) & 0x0f;
- data->pwm_temp[i][TEMP_PWM_HOT] = tmp & 0x0f;
- }
- for (i = 0; i < W83795_REG_TEMP_NUM; i++) {
- for (tmp = 0; tmp < 7; tmp++) {
- data->sf4_reg[i][SF4_TEMP][tmp] =
- w83795_read(client,
- W83795_REG_SF4_TEMP(i, tmp));
- data->sf4_reg[i][SF4_PWM][tmp] =
- w83795_read(client, W83795_REG_SF4_PWM(i, tmp));
- }
- }
-
- /* Setup PWM Register */
- for (i = 0; i < 3; i++) {
- data->setup_pwm[i] =
- w83795_read(client, W83795_REG_SETUP_PWM(i));
- }
-
- /* alarm and beep */
- for (i = 0; i < ALARM_BEEP_REG_NUM; i++) {
- data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i));
- data->beeps[i] = w83795_read(client, W83795_REG_BEEP(i));
- }
err = w83795_handle_files(dev, device_create_file);
if (err)
i2c_del_driver(&w83795_driver);
}
-MODULE_AUTHOR("Wei Song");
+MODULE_AUTHOR("Wei Song, Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("W83795G/ADG hardware monitoring driver");
MODULE_LICENSE("GPL");