diff options
| author | Jean Delvare <khali@linux-fr.org> | 2009-12-09 14:36:03 -0500 |
|---|---|---|
| committer | Jean Delvare <khali@linux-fr.org> | 2009-12-09 14:36:03 -0500 |
| commit | cffb9dd07fea8865093f6ccfb51d686487b89415 (patch) | |
| tree | 3390cdab4076372dc7ca60207d97e37420923b1f | |
| parent | f99318b2540da75e663603e1a0faef30a3bb0c92 (diff) | |
hwmon: (adt7475) Rework voltage inputs handling
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 <khali@linux-fr.org>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Jordan Crouse <jordan@cosmicpenguin.net>
Cc: "Darrick J. Wong" <djwong@us.ibm.com>
| -rw-r--r-- | drivers/hwmon/adt7475.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 188ae428ccdd..e9f69ee197d7 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | 39 | ||
| 40 | /* 7475 Common Registers */ | 40 | /* 7475 Common Registers */ |
| 41 | 41 | ||
| 42 | #define REG_VOLTAGE_BASE 0x21 | 42 | #define REG_VOLTAGE_BASE 0x20 |
| 43 | #define REG_TEMP_BASE 0x25 | 43 | #define REG_TEMP_BASE 0x25 |
| 44 | #define REG_TACH_BASE 0x28 | 44 | #define REG_TACH_BASE 0x28 |
| 45 | #define REG_PWM_BASE 0x30 | 45 | #define REG_PWM_BASE 0x30 |
| @@ -51,8 +51,8 @@ | |||
| 51 | #define REG_STATUS1 0x41 | 51 | #define REG_STATUS1 0x41 |
| 52 | #define REG_STATUS2 0x42 | 52 | #define REG_STATUS2 0x42 |
| 53 | 53 | ||
| 54 | #define REG_VOLTAGE_MIN_BASE 0x46 | 54 | #define REG_VOLTAGE_MIN_BASE 0x44 |
| 55 | #define REG_VOLTAGE_MAX_BASE 0x47 | 55 | #define REG_VOLTAGE_MAX_BASE 0x45 |
| 56 | 56 | ||
| 57 | #define REG_TEMP_MIN_BASE 0x4E | 57 | #define REG_TEMP_MIN_BASE 0x4E |
| 58 | #define REG_TEMP_MAX_BASE 0x4F | 58 | #define REG_TEMP_MAX_BASE 0x4F |
| @@ -85,7 +85,7 @@ | |||
| 85 | 85 | ||
| 86 | /* ADT7475 Settings */ | 86 | /* ADT7475 Settings */ |
| 87 | 87 | ||
| 88 | #define ADT7475_VOLTAGE_COUNT 2 | 88 | #define ADT7475_VOLTAGE_COUNT 5 /* Not counting Vtt */ |
| 89 | #define ADT7475_TEMP_COUNT 3 | 89 | #define ADT7475_TEMP_COUNT 3 |
| 90 | #define ADT7475_TACH_COUNT 4 | 90 | #define ADT7475_TACH_COUNT 4 |
| 91 | #define ADT7475_PWM_COUNT 3 | 91 | #define ADT7475_PWM_COUNT 3 |
| @@ -137,8 +137,9 @@ struct adt7475_data { | |||
| 137 | 137 | ||
| 138 | u8 config4; | 138 | u8 config4; |
| 139 | u8 config5; | 139 | u8 config5; |
| 140 | u8 has_voltage; | ||
| 140 | u16 alarms; | 141 | u16 alarms; |
| 141 | u16 voltage[3][3]; | 142 | u16 voltage[3][6]; |
| 142 | u16 temp[7][3]; | 143 | u16 temp[7][3]; |
| 143 | u16 tach[2][4]; | 144 | u16 tach[2][4]; |
| 144 | u8 pwm[4][3]; | 145 | u8 pwm[4][3]; |
| @@ -201,26 +202,30 @@ static inline u16 rpm2tach(unsigned long rpm) | |||
| 201 | return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF); | 202 | return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF); |
| 202 | } | 203 | } |
| 203 | 204 | ||
| 204 | static inline int reg2vcc(u16 reg) | 205 | /* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */ |
| 205 | { | 206 | static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = { |
| 206 | return (4296 * reg) / 1000; | 207 | { 45, 94 }, /* +2.5V */ |
| 207 | } | 208 | { 175, 525 }, /* Vccp */ |
| 209 | { 68, 71 }, /* Vcc */ | ||
| 210 | { 93, 47 }, /* +5V */ | ||
| 211 | { 120, 20 }, /* +12V */ | ||
| 212 | { 45, 45 }, /* Vtt */ | ||
| 213 | }; | ||
| 208 | 214 | ||
| 209 | static inline int reg2vccp(u16 reg) | 215 | static inline int reg2volt(int channel, u16 reg) |
| 210 | { | 216 | { |
| 211 | return (2929 * reg) / 1000; | 217 | const int *r = adt7473_in_scaling[channel]; |
| 212 | } | ||
| 213 | 218 | ||
| 214 | static inline u16 vcc2reg(long vcc) | 219 | return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024); |
| 215 | { | ||
| 216 | vcc = SENSORS_LIMIT(vcc, 0, 4396); | ||
| 217 | return (vcc * 1000) / 4296; | ||
| 218 | } | 220 | } |
| 219 | 221 | ||
| 220 | static inline u16 vccp2reg(long vcc) | 222 | static inline u16 volt2reg(int channel, long volt) |
| 221 | { | 223 | { |
| 222 | vcc = SENSORS_LIMIT(vcc, 0, 2998); | 224 | const int *r = adt7473_in_scaling[channel]; |
| 223 | return (vcc * 1000) / 2929; | 225 | long reg; |
| 226 | |||
| 227 | reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250); | ||
| 228 | return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2); | ||
| 224 | } | 229 | } |
| 225 | 230 | ||
| 226 | static u16 adt7475_read_word(struct i2c_client *client, int reg) | 231 | static u16 adt7475_read_word(struct i2c_client *client, int reg) |
| @@ -276,12 +281,10 @@ static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, | |||
| 276 | switch (sattr->nr) { | 281 | switch (sattr->nr) { |
| 277 | case ALARM: | 282 | case ALARM: |
| 278 | return sprintf(buf, "%d\n", | 283 | return sprintf(buf, "%d\n", |
| 279 | (data->alarms >> (sattr->index + 1)) & 1); | 284 | (data->alarms >> sattr->index) & 1); |
| 280 | default: | 285 | default: |
| 281 | val = data->voltage[sattr->nr][sattr->index]; | 286 | val = data->voltage[sattr->nr][sattr->index]; |
| 282 | return sprintf(buf, "%d\n", | 287 | return sprintf(buf, "%d\n", reg2volt(sattr->index, val)); |
| 283 | sattr->index == | ||
| 284 | 0 ? reg2vccp(val) : reg2vcc(val)); | ||
| 285 | } | 288 | } |
| 286 | } | 289 | } |
| 287 | 290 | ||
| @@ -300,8 +303,7 @@ static ssize_t set_voltage(struct device *dev, struct device_attribute *attr, | |||
| 300 | 303 | ||
| 301 | mutex_lock(&data->lock); | 304 | mutex_lock(&data->lock); |
| 302 | 305 | ||
| 303 | data->voltage[sattr->nr][sattr->index] = | 306 | data->voltage[sattr->nr][sattr->index] = volt2reg(sattr->index, val); |
| 304 | sattr->index ? vcc2reg(val) : vccp2reg(val); | ||
| 305 | 307 | ||
| 306 | if (sattr->nr == MIN) | 308 | if (sattr->nr == MIN) |
| 307 | reg = VOLTAGE_MIN_REG(sattr->index); | 309 | reg = VOLTAGE_MIN_REG(sattr->index); |
| @@ -815,18 +817,18 @@ static ssize_t set_pwm_at_crit(struct device *dev, | |||
| 815 | return count; | 817 | return count; |
| 816 | } | 818 | } |
| 817 | 819 | ||
| 818 | static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 0); | 820 | static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 1); |
| 819 | static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage, | 821 | static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage, |
| 820 | set_voltage, MAX, 0); | 822 | set_voltage, MAX, 1); |
| 821 | static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage, | 823 | static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage, |
| 822 | set_voltage, MIN, 0); | 824 | set_voltage, MIN, 1); |
| 823 | static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0); | 825 | static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1); |
| 824 | static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 1); | 826 | static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 2); |
| 825 | static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage, | 827 | static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage, |
| 826 | set_voltage, MAX, 1); | 828 | set_voltage, MAX, 2); |
| 827 | static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage, | 829 | static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage, |
| 828 | set_voltage, MIN, 1); | 830 | set_voltage, MIN, 2); |
| 829 | static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1); | 831 | static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 2); |
| 830 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0); | 832 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0); |
| 831 | static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0); | 833 | static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0); |
| 832 | static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0); | 834 | static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0); |
| @@ -1050,6 +1052,12 @@ static int adt7475_probe(struct i2c_client *client, | |||
| 1050 | mutex_init(&data->lock); | 1052 | mutex_init(&data->lock); |
| 1051 | i2c_set_clientdata(client, data); | 1053 | i2c_set_clientdata(client, data); |
| 1052 | 1054 | ||
| 1055 | /* Initialize device-specific values */ | ||
| 1056 | switch (id->driver_data) { | ||
| 1057 | default: | ||
| 1058 | data->has_voltage = 0x06; /* in1, in2 */ | ||
| 1059 | } | ||
| 1060 | |||
| 1053 | /* Call adt7475_read_pwm for all pwm's as this will reprogram any | 1061 | /* Call adt7475_read_pwm for all pwm's as this will reprogram any |
| 1054 | pwm's which are disabled to manual mode with 0% duty cycle */ | 1062 | pwm's which are disabled to manual mode with 0% duty cycle */ |
| 1055 | for (i = 0; i < ADT7475_PWM_COUNT; i++) | 1063 | for (i = 0; i < ADT7475_PWM_COUNT; i++) |
| @@ -1176,10 +1184,13 @@ static struct adt7475_data *adt7475_update_device(struct device *dev) | |||
| 1176 | data->alarms |= adt7475_read(REG_STATUS1); | 1184 | data->alarms |= adt7475_read(REG_STATUS1); |
| 1177 | 1185 | ||
| 1178 | ext = adt7475_read(REG_EXTEND1); | 1186 | ext = adt7475_read(REG_EXTEND1); |
| 1179 | for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) | 1187 | for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) { |
| 1188 | if (!(data->has_voltage & (1 << i))) | ||
| 1189 | continue; | ||
| 1180 | data->voltage[INPUT][i] = | 1190 | data->voltage[INPUT][i] = |
| 1181 | (adt7475_read(VOLTAGE_REG(i)) << 2) | | 1191 | (adt7475_read(VOLTAGE_REG(i)) << 2) | |
| 1182 | ((ext >> ((i + 1) * 2)) & 3); | 1192 | ((ext >> (i * 2)) & 3); |
| 1193 | } | ||
| 1183 | 1194 | ||
| 1184 | ext = adt7475_read(REG_EXTEND2); | 1195 | ext = adt7475_read(REG_EXTEND2); |
| 1185 | for (i = 0; i < ADT7475_TEMP_COUNT; i++) | 1196 | for (i = 0; i < ADT7475_TEMP_COUNT; i++) |
| @@ -1205,6 +1216,8 @@ static struct adt7475_data *adt7475_update_device(struct device *dev) | |||
| 1205 | data->config5 = adt7475_read(REG_CONFIG5); | 1216 | data->config5 = adt7475_read(REG_CONFIG5); |
| 1206 | 1217 | ||
| 1207 | for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) { | 1218 | for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) { |
| 1219 | if (!(data->has_voltage & (1 << i))) | ||
| 1220 | continue; | ||
| 1208 | /* Adjust values so they match the input precision */ | 1221 | /* Adjust values so they match the input precision */ |
| 1209 | data->voltage[MIN][i] = | 1222 | data->voltage[MIN][i] = |
| 1210 | adt7475_read(VOLTAGE_MIN_REG(i)) << 2; | 1223 | adt7475_read(VOLTAGE_MIN_REG(i)) << 2; |
