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 /drivers | |
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>
Diffstat (limited to 'drivers')
-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; |