aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/w83795.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2010-10-28 14:31:47 -0400
committerJean Delvare <khali@endymion.delvare>2010-10-28 14:31:47 -0400
commit01879a855fb6bdb3fb820344a7a145de8a5cdbda (patch)
tree152e9a958bfdd71692455d18348623b1cbb40929 /drivers/hwmon/w83795.c
parent0e256018b0f35d1b22ca37e1d0e207f7ba3d0076 (diff)
hwmon: (w83795) Fix PWM duty cycle frequency attributes
The PWM duty cycle frequenty attributes are improperly named (fanN_div instead of pwmN_div) and contain raw values instead of actual frequencies. Rename them and fix their contents. Also improve the logic when the user asks for a new frequency, to always pick the closest supported frequency. The algorithm could certainly be optimized, but the operation is infrequent enough that I don't think it's worth the effort. Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/w83795.c')
-rw-r--r--drivers/hwmon/w83795.c90
1 files changed, 62 insertions, 28 deletions
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
index 458fb297f696..58c61f11ed66 100644
--- a/drivers/hwmon/w83795.c
+++ b/drivers/hwmon/w83795.c
@@ -200,7 +200,6 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
200#define W83795_REG_FCMS2 0x208 200#define W83795_REG_FCMS2 0x208
201#define W83795_REG_TFMR(index) (0x202 + (index)) 201#define W83795_REG_TFMR(index) (0x202 + (index))
202#define W83795_REG_FOMC 0x20F 202#define W83795_REG_FOMC 0x20F
203#define W83795_REG_FOPFP(index) (0x218 + (index))
204 203
205#define W83795_REG_TSS(index) (0x209 + (index)) 204#define W83795_REG_TSS(index) (0x209 + (index))
206 205
@@ -208,18 +207,13 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
208#define PWM_START 1 207#define PWM_START 1
209#define PWM_NONSTOP 2 208#define PWM_NONSTOP 2
210#define PWM_STOP_TIME 3 209#define PWM_STOP_TIME 3
211#define PWM_DIV 4 210#define PWM_FREQ 4
212#define W83795_REG_PWM(index, nr) \ 211#define W83795_REG_PWM(index, nr) \
213 (((nr) == 0 ? 0x210 : \ 212 (((nr) == 0 ? 0x210 : \
214 (nr) == 1 ? 0x220 : \ 213 (nr) == 1 ? 0x220 : \
215 (nr) == 2 ? 0x228 : \ 214 (nr) == 2 ? 0x228 : \
216 (nr) == 3 ? 0x230 : 0x218) + (index)) 215 (nr) == 3 ? 0x230 : 0x218) + (index))
217 216
218#define W83795_REG_FOPFP_DIV(index) \
219 (((index) < 8) ? ((index) + 1) : \
220 ((index) == 8) ? 12 : \
221 (16 << ((index) - 9)))
222
223#define W83795_REG_FTSH(index) (0x240 + (index) * 2) 217#define W83795_REG_FTSH(index) (0x240 + (index) * 2)
224#define W83795_REG_FTSL(index) (0x241 + (index) * 2) 218#define W83795_REG_FTSL(index) (0x241 + (index) * 2)
225#define W83795_REG_TFTS 0x250 219#define W83795_REG_TFTS 0x250
@@ -304,6 +298,50 @@ static inline s8 temp_to_reg(long val, s8 min, s8 max)
304 return SENSORS_LIMIT((val < 0 ? -val : val) / 1000, min, max); 298 return SENSORS_LIMIT((val < 0 ? -val : val) / 1000, min, max);
305} 299}
306 300
301static const u16 pwm_freq_cksel0[16] = {
302 1024, 512, 341, 256, 205, 171, 146, 128,
303 85, 64, 32, 16, 8, 4, 2, 1
304};
305
306static unsigned int pwm_freq_from_reg(u8 reg, u16 clkin)
307{
308 unsigned long base_clock;
309
310 if (reg & 0x80) {
311 base_clock = clkin * 1000 / ((clkin == 48000) ? 384 : 256);
312 return base_clock / ((reg & 0x7f) + 1);
313 } else
314 return pwm_freq_cksel0[reg & 0x0f];
315}
316
317static u8 pwm_freq_to_reg(unsigned long val, u16 clkin)
318{
319 unsigned long base_clock;
320 u8 reg0, reg1;
321 unsigned long best0, best1;
322
323 /* Best fit for cksel = 0 */
324 for (reg0 = 0; reg0 < ARRAY_SIZE(pwm_freq_cksel0) - 1; reg0++) {
325 if (val > (pwm_freq_cksel0[reg0] +
326 pwm_freq_cksel0[reg0 + 1]) / 2)
327 break;
328 }
329 if (val < 375) /* cksel = 1 can't beat this */
330 return reg0;
331 best0 = pwm_freq_cksel0[reg0];
332
333 /* Best fit for cksel = 1 */
334 base_clock = clkin * 1000 / ((clkin == 48000) ? 384 : 256);
335 reg1 = SENSORS_LIMIT(DIV_ROUND_CLOSEST(base_clock, val), 1, 128);
336 best1 = base_clock / reg1;
337 reg1 = 0x80 | (reg1 - 1);
338
339 /* Choose the closest one */
340 if (abs(val - best0) > abs(val - best1))
341 return reg1;
342 else
343 return reg0;
344}
307 345
308enum chip_types {w83795g, w83795adg}; 346enum chip_types {w83795g, w83795adg};
309 347
@@ -343,7 +381,8 @@ struct w83795_data {
343 * no config register, only affected by chip 381 * no config register, only affected by chip
344 * type */ 382 * type */
345 u8 pwm[8][5]; /* Register value, output, start, non stop, stop 383 u8 pwm[8][5]; /* Register value, output, start, non stop, stop
346 * time, div */ 384 * time, freq */
385 u16 clkin; /* CLKIN frequency in kHz */
347 u8 pwm_fcms[2]; /* Register value */ 386 u8 pwm_fcms[2]; /* Register value */
348 u8 pwm_tfmr[6]; /* Register value */ 387 u8 pwm_tfmr[6]; /* Register value */
349 u8 pwm_fomc; /* Register value */ 388 u8 pwm_fomc; /* Register value */
@@ -688,14 +727,14 @@ show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
688 to_sensor_dev_attr_2(attr); 727 to_sensor_dev_attr_2(attr);
689 int nr = sensor_attr->nr; 728 int nr = sensor_attr->nr;
690 int index = sensor_attr->index; 729 int index = sensor_attr->index;
691 u16 val; 730 unsigned int val;
692 731
693 switch (nr) { 732 switch (nr) {
694 case PWM_STOP_TIME: 733 case PWM_STOP_TIME:
695 val = time_from_reg(data->pwm[index][nr]); 734 val = time_from_reg(data->pwm[index][nr]);
696 break; 735 break;
697 case PWM_DIV: 736 case PWM_FREQ:
698 val = W83795_REG_FOPFP_DIV(data->pwm[index][nr] & 0x0f); 737 val = pwm_freq_from_reg(data->pwm[index][nr], data->clkin);
699 break; 738 break;
700 default: 739 default:
701 val = data->pwm[index][nr]; 740 val = data->pwm[index][nr];
@@ -716,7 +755,6 @@ store_pwm(struct device *dev, struct device_attribute *attr,
716 int nr = sensor_attr->nr; 755 int nr = sensor_attr->nr;
717 int index = sensor_attr->index; 756 int index = sensor_attr->index;
718 unsigned long val; 757 unsigned long val;
719 int i;
720 758
721 if (strict_strtoul(buf, 10, &val) < 0) 759 if (strict_strtoul(buf, 10, &val) < 0)
722 return -EINVAL; 760 return -EINVAL;
@@ -726,28 +764,17 @@ store_pwm(struct device *dev, struct device_attribute *attr,
726 case PWM_STOP_TIME: 764 case PWM_STOP_TIME:
727 val = time_to_reg(val); 765 val = time_to_reg(val);
728 break; 766 break;
729 case PWM_DIV: 767 case PWM_FREQ:
730 for (i = 0; i < 16; i++) { 768 val = pwm_freq_to_reg(val, data->clkin);
731 if (W83795_REG_FOPFP_DIV(i) == val) {
732 val = i;
733 break;
734 }
735 }
736 if (i >= 16)
737 goto err_end;
738 val |= w83795_read(client, W83795_REG_PWM(index, nr)) & 0x80;
739 break; 769 break;
740 default: 770 default:
741 val = SENSORS_LIMIT(val, 0, 0xff); 771 val = SENSORS_LIMIT(val, 0, 0xff);
742 break; 772 break;
743 } 773 }
744 w83795_write(client, W83795_REG_PWM(index, nr), val); 774 w83795_write(client, W83795_REG_PWM(index, nr), val);
745 data->pwm[index][nr] = val & 0xff; 775 data->pwm[index][nr] = val;
746 mutex_unlock(&data->update_lock); 776 mutex_unlock(&data->update_lock);
747 return count; 777 return count;
748err_end:
749 mutex_unlock(&data->update_lock);
750 return -EINVAL;
751} 778}
752 779
753static ssize_t 780static ssize_t
@@ -1502,8 +1529,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
1502 show_pwm, store_pwm, PWM_START, index - 1), \ 1529 show_pwm, store_pwm, PWM_START, index - 1), \
1503 SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO, \ 1530 SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO, \
1504 show_pwm, store_pwm, PWM_STOP_TIME, index - 1), \ 1531 show_pwm, store_pwm, PWM_STOP_TIME, index - 1), \
1505 SENSOR_ATTR_2(fan##index##_div, S_IWUSR | S_IRUGO, \ 1532 SENSOR_ATTR_2(pwm##index##_freq, S_IWUSR | S_IRUGO, \
1506 show_pwm, store_pwm, PWM_DIV, index - 1), \ 1533 show_pwm, store_pwm, PWM_FREQ, index - 1), \
1507 SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \ 1534 SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \
1508 show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \ 1535 show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \
1509 SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \ 1536 SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \
@@ -1685,6 +1712,10 @@ static const struct sensor_device_attribute_2 sda_single_files[] = {
1685 1712
1686static void w83795_init_client(struct i2c_client *client) 1713static void w83795_init_client(struct i2c_client *client)
1687{ 1714{
1715 struct w83795_data *data = i2c_get_clientdata(client);
1716 static const u16 clkin[4] = { /* in kHz */
1717 14318, 24000, 33333, 48000
1718 };
1688 u8 config; 1719 u8 config;
1689 1720
1690 if (reset) 1721 if (reset)
@@ -1697,6 +1728,9 @@ static void w83795_init_client(struct i2c_client *client)
1697 w83795_write(client, W83795_REG_CONFIG, 1728 w83795_write(client, W83795_REG_CONFIG,
1698 config | W83795_REG_CONFIG_START); 1729 config | W83795_REG_CONFIG_START);
1699 } 1730 }
1731
1732 data->clkin = clkin[(config >> 3) & 0x3];
1733 dev_dbg(&client->dev, "clkin = %u kHz\n", data->clkin);
1700} 1734}
1701 1735
1702static int w83795_get_device_id(struct i2c_client *client) 1736static int w83795_get_device_id(struct i2c_client *client)