aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorCarlos Olalla Martinez <com.ea@tinet.org>2007-06-09 10:11:16 -0400
committerMark M. Hoffman <mhoffman@lightlink.com>2007-07-19 14:22:13 -0400
commit1550cb6d7e78c7cfdd7b48bee6809795d43d6a33 (patch)
tree97cac49a63ef9db71f59af6dd0cdd30100dc83de /drivers/hwmon
parent08a8f6e9e63a4317f716749ba9f828351bd4af35 (diff)
hwmon/w83627hf: Add PWM frequency selection support
Signed-off-by: Carlos Olalla <com.ea@tinet.org> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/w83627hf.c141
1 files changed, 140 insertions, 1 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 72aee3c0e8de..cd953604c38f 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -220,6 +220,18 @@ static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
220#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \ 220#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
221 regpwm_627hf[(nr) - 1] : regpwm[(nr) - 1]) 221 regpwm_627hf[(nr) - 1] : regpwm[(nr) - 1])
222 222
223#define W83627HF_REG_PWM_FREQ 0x5C /* Only for the 627HF */
224
225#define W83637HF_REG_PWM_FREQ1 0x00 /* 697HF/687THF too */
226#define W83637HF_REG_PWM_FREQ2 0x02 /* 697HF/687THF too */
227#define W83637HF_REG_PWM_FREQ3 0x10 /* 687THF too */
228
229static const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1,
230 W83637HF_REG_PWM_FREQ2,
231 W83637HF_REG_PWM_FREQ3 };
232
233#define W83627HF_BASE_PWM_FREQ 46870
234
223#define W83781D_REG_I2C_ADDR 0x48 235#define W83781D_REG_I2C_ADDR 0x48
224#define W83781D_REG_I2C_SUBADDR 0x4A 236#define W83781D_REG_I2C_SUBADDR 0x4A
225 237
@@ -267,6 +279,49 @@ static int TEMP_FROM_REG(u8 reg)
267 279
268#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) 280#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
269 281
282static inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
283{
284 unsigned long freq;
285 freq = W83627HF_BASE_PWM_FREQ >> reg;
286 return freq;
287}
288static inline u8 pwm_freq_to_reg_627hf(unsigned long val)
289{
290 u8 i;
291 /* Only 5 dividers (1 2 4 8 16)
292 Search for the nearest available frequency */
293 for (i = 0; i < 4; i++) {
294 if (val > (((W83627HF_BASE_PWM_FREQ >> i) +
295 (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2))
296 break;
297 }
298 return i;
299}
300
301static inline unsigned long pwm_freq_from_reg(u8 reg)
302{
303 /* Clock bit 8 -> 180 kHz or 24 MHz */
304 unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL;
305
306 reg &= 0x7f;
307 /* This should not happen but anyway... */
308 if (reg == 0)
309 reg++;
310 return (clock / (reg << 8));
311}
312static inline u8 pwm_freq_to_reg(unsigned long val)
313{
314 /* Minimum divider value is 0x01 and maximum is 0x7F */
315 if (val >= 93750) /* The highest we can do */
316 return 0x01;
317 if (val >= 720) /* Use 24 MHz clock */
318 return (24000000UL / (val << 8));
319 if (val < 6) /* The lowest we can do */
320 return 0xFF;
321 else /* Use 180 kHz clock */
322 return (0x80 | (180000UL / (val << 8)));
323}
324
270#define BEEP_MASK_FROM_REG(val) (val) 325#define BEEP_MASK_FROM_REG(val) (val)
271#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) 326#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff)
272#define BEEP_ENABLE_TO_REG(val) ((val)?1:0) 327#define BEEP_ENABLE_TO_REG(val) ((val)?1:0)
@@ -316,6 +371,7 @@ struct w83627hf_data {
316 u32 beep_mask; /* Register encoding, combined */ 371 u32 beep_mask; /* Register encoding, combined */
317 u8 beep_enable; /* Boolean */ 372 u8 beep_enable; /* Boolean */
318 u8 pwm[3]; /* Register value */ 373 u8 pwm[3]; /* Register value */
374 u8 pwm_freq[3]; /* Register value */
319 u16 sens[3]; /* 782D/783S only. 375 u16 sens[3]; /* 782D/783S only.
320 1 = pentium diode; 2 = 3904 diode; 376 1 = pentium diode; 2 = 3904 diode;
321 3000-5000 = thermistor beta. 377 3000-5000 = thermistor beta.
@@ -852,6 +908,64 @@ sysfs_pwm(2);
852sysfs_pwm(3); 908sysfs_pwm(3);
853 909
854static ssize_t 910static ssize_t
911show_pwm_freq_reg(struct device *dev, char *buf, int nr)
912{
913 struct w83627hf_data *data = w83627hf_update_device(dev);
914 if (data->type == w83627hf)
915 return sprintf(buf, "%ld\n",
916 pwm_freq_from_reg_627hf(data->pwm_freq[nr - 1]));
917 else
918 return sprintf(buf, "%ld\n",
919 pwm_freq_from_reg(data->pwm_freq[nr - 1]));
920}
921
922static ssize_t
923store_pwm_freq_reg(struct device *dev, const char *buf, size_t count, int nr)
924{
925 struct w83627hf_data *data = dev_get_drvdata(dev);
926 static const u8 mask[]={0xF8, 0x8F};
927 u32 val;
928
929 val = simple_strtoul(buf, NULL, 10);
930
931 mutex_lock(&data->update_lock);
932
933 if (data->type == w83627hf) {
934 data->pwm_freq[nr - 1] = pwm_freq_to_reg_627hf(val);
935 w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
936 (data->pwm_freq[nr - 1] << ((nr - 1)*4)) |
937 (w83627hf_read_value(data,
938 W83627HF_REG_PWM_FREQ) & mask[nr - 1]));
939 } else {
940 data->pwm_freq[nr - 1] = pwm_freq_to_reg(val);
941 w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr - 1],
942 data->pwm_freq[nr - 1]);
943 }
944
945 mutex_unlock(&data->update_lock);
946 return count;
947}
948
949#define sysfs_pwm_freq(offset) \
950static ssize_t show_regs_pwm_freq_##offset(struct device *dev, \
951 struct device_attribute *attr, char *buf) \
952{ \
953 return show_pwm_freq_reg(dev, buf, offset); \
954} \
955static ssize_t \
956store_regs_pwm_freq_##offset(struct device *dev, \
957 struct device_attribute *attr, const char *buf, size_t count) \
958{ \
959 return store_pwm_freq_reg(dev, buf, count, offset); \
960} \
961static DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \
962 show_regs_pwm_freq_##offset, store_regs_pwm_freq_##offset);
963
964sysfs_pwm_freq(1);
965sysfs_pwm_freq(2);
966sysfs_pwm_freq(3);
967
968static ssize_t
855show_sensor_reg(struct device *dev, char *buf, int nr) 969show_sensor_reg(struct device *dev, char *buf, int nr)
856{ 970{
857 struct w83627hf_data *data = w83627hf_update_device(dev); 971 struct w83627hf_data *data = w83627hf_update_device(dev);
@@ -1077,6 +1191,9 @@ static struct attribute *w83627hf_attributes_opt[] = {
1077 1191
1078 &dev_attr_pwm3.attr, 1192 &dev_attr_pwm3.attr,
1079 1193
1194 &dev_attr_pwm1_freq.attr,
1195 &dev_attr_pwm2_freq.attr,
1196 &dev_attr_pwm3_freq.attr,
1080 NULL 1197 NULL
1081}; 1198};
1082 1199
@@ -1139,7 +1256,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
1139 || (err = device_create_file(dev, &dev_attr_in5_max)) 1256 || (err = device_create_file(dev, &dev_attr_in5_max))
1140 || (err = device_create_file(dev, &dev_attr_in6_input)) 1257 || (err = device_create_file(dev, &dev_attr_in6_input))
1141 || (err = device_create_file(dev, &dev_attr_in6_min)) 1258 || (err = device_create_file(dev, &dev_attr_in6_min))
1142 || (err = device_create_file(dev, &dev_attr_in6_max))) 1259 || (err = device_create_file(dev, &dev_attr_in6_max))
1260 || (err = device_create_file(dev, &dev_attr_pwm1_freq))
1261 || (err = device_create_file(dev, &dev_attr_pwm2_freq)))
1143 goto ERROR4; 1262 goto ERROR4;
1144 1263
1145 if (data->type != w83697hf) 1264 if (data->type != w83697hf)
@@ -1169,6 +1288,12 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
1169 if ((err = device_create_file(dev, &dev_attr_pwm3))) 1288 if ((err = device_create_file(dev, &dev_attr_pwm3)))
1170 goto ERROR4; 1289 goto ERROR4;
1171 1290
1291 if (data->type == w83637hf || data->type == w83687thf)
1292 if ((err = device_create_file(dev, &dev_attr_pwm1_freq))
1293 || (err = device_create_file(dev, &dev_attr_pwm2_freq))
1294 || (err = device_create_file(dev, &dev_attr_pwm3_freq)))
1295 goto ERROR4;
1296
1172 data->class_dev = hwmon_device_register(dev); 1297 data->class_dev = hwmon_device_register(dev);
1173 if (IS_ERR(data->class_dev)) { 1298 if (IS_ERR(data->class_dev)) {
1174 err = PTR_ERR(data->class_dev); 1299 err = PTR_ERR(data->class_dev);
@@ -1472,6 +1597,20 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
1472 (data->type == w83627hf || data->type == w83697hf)) 1597 (data->type == w83627hf || data->type == w83697hf))
1473 break; 1598 break;
1474 } 1599 }
1600 if (data->type == w83627hf) {
1601 u8 tmp = w83627hf_read_value(data,
1602 W83627HF_REG_PWM_FREQ);
1603 data->pwm_freq[0] = tmp & 0x07;
1604 data->pwm_freq[1] = (tmp >> 4) & 0x07;
1605 } else if (data->type != w83627thf) {
1606 for (i = 1; i <= 3; i++) {
1607 data->pwm_freq[i - 1] =
1608 w83627hf_read_value(data,
1609 W83637HF_REG_PWM_FREQ[i - 1]);
1610 if (i == 2 && (data->type == w83697hf))
1611 break;
1612 }
1613 }
1475 1614
1476 data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); 1615 data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
1477 data->temp_max = 1616 data->temp_max =