diff options
Diffstat (limited to 'drivers/hwmon/w83627hf.c')
-rw-r--r-- | drivers/hwmon/w83627hf.c | 153 |
1 files changed, 145 insertions, 8 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 12cb40a975de..1ce78179b005 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); |
@@ -1181,6 +1306,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) | |||
1181 | sysfs_remove_group(&dev->kobj, &w83627hf_group); | 1306 | sysfs_remove_group(&dev->kobj, &w83627hf_group); |
1182 | sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); | 1307 | sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); |
1183 | ERROR3: | 1308 | ERROR3: |
1309 | platform_set_drvdata(pdev, NULL); | ||
1184 | kfree(data); | 1310 | kfree(data); |
1185 | ERROR1: | 1311 | ERROR1: |
1186 | release_region(res->start, WINB_REGION_SIZE); | 1312 | release_region(res->start, WINB_REGION_SIZE); |
@@ -1193,11 +1319,11 @@ static int __devexit w83627hf_remove(struct platform_device *pdev) | |||
1193 | struct w83627hf_data *data = platform_get_drvdata(pdev); | 1319 | struct w83627hf_data *data = platform_get_drvdata(pdev); |
1194 | struct resource *res; | 1320 | struct resource *res; |
1195 | 1321 | ||
1196 | platform_set_drvdata(pdev, NULL); | ||
1197 | hwmon_device_unregister(data->class_dev); | 1322 | hwmon_device_unregister(data->class_dev); |
1198 | 1323 | ||
1199 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); | 1324 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); |
1200 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); | 1325 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); |
1326 | platform_set_drvdata(pdev, NULL); | ||
1201 | kfree(data); | 1327 | kfree(data); |
1202 | 1328 | ||
1203 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1329 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
@@ -1472,6 +1598,20 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
1472 | (data->type == w83627hf || data->type == w83697hf)) | 1598 | (data->type == w83627hf || data->type == w83697hf)) |
1473 | break; | 1599 | break; |
1474 | } | 1600 | } |
1601 | if (data->type == w83627hf) { | ||
1602 | u8 tmp = w83627hf_read_value(data, | ||
1603 | W83627HF_REG_PWM_FREQ); | ||
1604 | data->pwm_freq[0] = tmp & 0x07; | ||
1605 | data->pwm_freq[1] = (tmp >> 4) & 0x07; | ||
1606 | } else if (data->type != w83627thf) { | ||
1607 | for (i = 1; i <= 3; i++) { | ||
1608 | data->pwm_freq[i - 1] = | ||
1609 | w83627hf_read_value(data, | ||
1610 | W83637HF_REG_PWM_FREQ[i - 1]); | ||
1611 | if (i == 2 && (data->type == w83697hf)) | ||
1612 | break; | ||
1613 | } | ||
1614 | } | ||
1475 | 1615 | ||
1476 | data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); | 1616 | data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); |
1477 | data->temp_max = | 1617 | data->temp_max = |
@@ -1548,15 +1688,12 @@ static int __init w83627hf_device_add(unsigned short address, | |||
1548 | goto exit_device_put; | 1688 | goto exit_device_put; |
1549 | } | 1689 | } |
1550 | 1690 | ||
1551 | pdev->dev.platform_data = kmalloc(sizeof(struct w83627hf_sio_data), | 1691 | err = platform_device_add_data(pdev, sio_data, |
1552 | GFP_KERNEL); | 1692 | sizeof(struct w83627hf_sio_data)); |
1553 | if (!pdev->dev.platform_data) { | 1693 | if (err) { |
1554 | err = -ENOMEM; | ||
1555 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | 1694 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); |
1556 | goto exit_device_put; | 1695 | goto exit_device_put; |
1557 | } | 1696 | } |
1558 | memcpy(pdev->dev.platform_data, sio_data, | ||
1559 | sizeof(struct w83627hf_sio_data)); | ||
1560 | 1697 | ||
1561 | err = platform_device_add(pdev); | 1698 | err = platform_device_add(pdev); |
1562 | if (err) { | 1699 | if (err) { |