Skip to content

Commit

Permalink
hwmon: (adt7475) Rework voltage inputs handling
Browse files Browse the repository at this point in the history
Rework the handling of voltage inputs to make it possible and easy to
support more inputs. This will be needed for the upcoming ADT7490
support.

Signed-off-by: Jean Delvare <[email protected]>
Cc: Hans de Goede <[email protected]>
Cc: Jordan Crouse <[email protected]>
Cc: "Darrick J. Wong" <[email protected]>
  • Loading branch information
Jean Delvare committed Dec 9, 2009
1 parent f99318b commit cffb9dd
Showing 1 changed file with 48 additions and 35 deletions.
83 changes: 48 additions & 35 deletions drivers/hwmon/adt7475.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

/* 7475 Common Registers */

#define REG_VOLTAGE_BASE 0x21
#define REG_VOLTAGE_BASE 0x20
#define REG_TEMP_BASE 0x25
#define REG_TACH_BASE 0x28
#define REG_PWM_BASE 0x30
Expand All @@ -51,8 +51,8 @@
#define REG_STATUS1 0x41
#define REG_STATUS2 0x42

#define REG_VOLTAGE_MIN_BASE 0x46
#define REG_VOLTAGE_MAX_BASE 0x47
#define REG_VOLTAGE_MIN_BASE 0x44
#define REG_VOLTAGE_MAX_BASE 0x45

#define REG_TEMP_MIN_BASE 0x4E
#define REG_TEMP_MAX_BASE 0x4F
Expand Down Expand Up @@ -85,7 +85,7 @@

/* ADT7475 Settings */

#define ADT7475_VOLTAGE_COUNT 2
#define ADT7475_VOLTAGE_COUNT 5 /* Not counting Vtt */
#define ADT7475_TEMP_COUNT 3
#define ADT7475_TACH_COUNT 4
#define ADT7475_PWM_COUNT 3
Expand Down Expand Up @@ -137,8 +137,9 @@ struct adt7475_data {

u8 config4;
u8 config5;
u8 has_voltage;
u16 alarms;
u16 voltage[3][3];
u16 voltage[3][6];
u16 temp[7][3];
u16 tach[2][4];
u8 pwm[4][3];
Expand Down Expand Up @@ -201,26 +202,30 @@ static inline u16 rpm2tach(unsigned long rpm)
return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF);
}

static inline int reg2vcc(u16 reg)
{
return (4296 * reg) / 1000;
}
/* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */
static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = {
{ 45, 94 }, /* +2.5V */
{ 175, 525 }, /* Vccp */
{ 68, 71 }, /* Vcc */
{ 93, 47 }, /* +5V */
{ 120, 20 }, /* +12V */
{ 45, 45 }, /* Vtt */
};

static inline int reg2vccp(u16 reg)
static inline int reg2volt(int channel, u16 reg)
{
return (2929 * reg) / 1000;
}
const int *r = adt7473_in_scaling[channel];

static inline u16 vcc2reg(long vcc)
{
vcc = SENSORS_LIMIT(vcc, 0, 4396);
return (vcc * 1000) / 4296;
return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024);
}

static inline u16 vccp2reg(long vcc)
static inline u16 volt2reg(int channel, long volt)
{
vcc = SENSORS_LIMIT(vcc, 0, 2998);
return (vcc * 1000) / 2929;
const int *r = adt7473_in_scaling[channel];
long reg;

reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250);
return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2);
}

static u16 adt7475_read_word(struct i2c_client *client, int reg)
Expand Down Expand Up @@ -276,12 +281,10 @@ static ssize_t show_voltage(struct device *dev, struct device_attribute *attr,
switch (sattr->nr) {
case ALARM:
return sprintf(buf, "%d\n",
(data->alarms >> (sattr->index + 1)) & 1);
(data->alarms >> sattr->index) & 1);
default:
val = data->voltage[sattr->nr][sattr->index];
return sprintf(buf, "%d\n",
sattr->index ==
0 ? reg2vccp(val) : reg2vcc(val));
return sprintf(buf, "%d\n", reg2volt(sattr->index, val));
}
}

Expand All @@ -300,8 +303,7 @@ static ssize_t set_voltage(struct device *dev, struct device_attribute *attr,

mutex_lock(&data->lock);

data->voltage[sattr->nr][sattr->index] =
sattr->index ? vcc2reg(val) : vccp2reg(val);
data->voltage[sattr->nr][sattr->index] = volt2reg(sattr->index, val);

if (sattr->nr == MIN)
reg = VOLTAGE_MIN_REG(sattr->index);
Expand Down Expand Up @@ -815,18 +817,18 @@ static ssize_t set_pwm_at_crit(struct device *dev,
return count;
}

static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 0);
static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 1);
static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage,
set_voltage, MAX, 0);
set_voltage, MAX, 1);
static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage,
set_voltage, MIN, 0);
static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0);
static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 1);
set_voltage, MIN, 1);
static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1);
static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 2);
static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage,
set_voltage, MAX, 1);
set_voltage, MAX, 2);
static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage,
set_voltage, MIN, 1);
static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1);
set_voltage, MIN, 2);
static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 2);
static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0);
static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0);
static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0);
Expand Down Expand Up @@ -1050,6 +1052,12 @@ static int adt7475_probe(struct i2c_client *client,
mutex_init(&data->lock);
i2c_set_clientdata(client, data);

/* Initialize device-specific values */
switch (id->driver_data) {
default:
data->has_voltage = 0x06; /* in1, in2 */
}

/* Call adt7475_read_pwm for all pwm's as this will reprogram any
pwm's which are disabled to manual mode with 0% duty cycle */
for (i = 0; i < ADT7475_PWM_COUNT; i++)
Expand Down Expand Up @@ -1176,10 +1184,13 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
data->alarms |= adt7475_read(REG_STATUS1);

ext = adt7475_read(REG_EXTEND1);
for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++)
for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
if (!(data->has_voltage & (1 << i)))
continue;
data->voltage[INPUT][i] =
(adt7475_read(VOLTAGE_REG(i)) << 2) |
((ext >> ((i + 1) * 2)) & 3);
((ext >> (i * 2)) & 3);
}

ext = adt7475_read(REG_EXTEND2);
for (i = 0; i < ADT7475_TEMP_COUNT; i++)
Expand All @@ -1205,6 +1216,8 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
data->config5 = adt7475_read(REG_CONFIG5);

for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
if (!(data->has_voltage & (1 << i)))
continue;
/* Adjust values so they match the input precision */
data->voltage[MIN][i] =
adt7475_read(VOLTAGE_MIN_REG(i)) << 2;
Expand Down

0 comments on commit cffb9dd

Please sign in to comment.