diff options
author | Carlos Olalla Martinez <com.ea@tinet.org> | 2007-06-09 10:11:16 -0400 |
---|---|---|
committer | Mark M. Hoffman <mhoffman@lightlink.com> | 2007-07-19 14:22:13 -0400 |
commit | 1550cb6d7e78c7cfdd7b48bee6809795d43d6a33 (patch) | |
tree | 97cac49a63ef9db71f59af6dd0cdd30100dc83de /drivers/hwmon/w83627hf.c | |
parent | 08a8f6e9e63a4317f716749ba9f828351bd4af35 (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/w83627hf.c')
-rw-r--r-- | drivers/hwmon/w83627hf.c | 141 |
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 | |||
229 | static 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 | ||
282 | static 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 | } | ||
288 | static 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 | |||
301 | static 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 | } | ||
312 | static 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); | |||
852 | sysfs_pwm(3); | 908 | sysfs_pwm(3); |
853 | 909 | ||
854 | static ssize_t | 910 | static ssize_t |
911 | show_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 | |||
922 | static ssize_t | ||
923 | store_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) \ | ||
950 | static 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 | } \ | ||
955 | static ssize_t \ | ||
956 | store_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 | } \ | ||
961 | static DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \ | ||
962 | show_regs_pwm_freq_##offset, store_regs_pwm_freq_##offset); | ||
963 | |||
964 | sysfs_pwm_freq(1); | ||
965 | sysfs_pwm_freq(2); | ||
966 | sysfs_pwm_freq(3); | ||
967 | |||
968 | static ssize_t | ||
855 | show_sensor_reg(struct device *dev, char *buf, int nr) | 969 | show_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 = |