Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (lm85) Add support for ADT7468 high-frequency PWM mode

The ADT7468 supports a high-frequency PWM output mode where all PWM
outputs are driven by a 22.5 kHz clock. Add support for this mode, and
document it, as it may surprise the user that setting one PWM output
frequency also affects the other PWM outputs.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Darrick J. Wong <djwong@us.ibm.com>
Acked-by: Guenter Roeck <guenter.roeck@ericsson.com>

authored by

Jean Delvare and committed by
Jean Delvare
f6c61cff c36364db

+35 -7
+7
Documentation/hwmon/lm85
··· 101 101 described in the documentation. The current lm85 driver does not show the 102 102 offset register. 103 103 104 + The ADT7468 has a high-frequency PWM mode, where all PWM outputs are 105 + driven by a 22.5 kHz clock. This is a global mode, not per-PWM output, 106 + which means that setting any PWM frequency above 11.3 kHz will switch 107 + all 3 PWM outputs to a 22.5 kHz frequency. Conversely, setting any PWM 108 + frequency below 11.3 kHz will switch all 3 PWM outputs to a frequency 109 + between 10 and 100 Hz, which can then be tuned separately. 110 + 104 111 See the vendor datasheets for more information. There is application note 105 112 from National (AN-1260) with some additional information about the LM85. 106 113 The Analog Devices datasheet is very detailed and describes a procedure for
+28 -7
drivers/hwmon/lm85.c
··· 64 64 #define LM85_REG_VERSTEP 0x3f 65 65 66 66 #define ADT7468_REG_CFG5 0x7c 67 - #define ADT7468_OFF64 0x01 67 + #define ADT7468_OFF64 (1 << 0) 68 + #define ADT7468_HFPWM (1 << 1) 68 69 #define IS_ADT7468_OFF64(data) \ 69 70 ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64)) 71 + #define IS_ADT7468_HFPWM(data) \ 72 + ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_HFPWM)) 70 73 71 74 /* These are the recognized values for the above regs */ 72 75 #define LM85_COMPANY_NATIONAL 0x01 ··· 570 567 { 571 568 int nr = to_sensor_dev_attr(attr)->index; 572 569 struct lm85_data *data = lm85_update_device(dev); 573 - return sprintf(buf, "%d\n", FREQ_FROM_REG(data->freq_map, 574 - data->pwm_freq[nr])); 570 + int freq; 571 + 572 + if (IS_ADT7468_HFPWM(data)) 573 + freq = 22500; 574 + else 575 + freq = FREQ_FROM_REG(data->freq_map, data->pwm_freq[nr]); 576 + 577 + return sprintf(buf, "%d\n", freq); 575 578 } 576 579 577 580 static ssize_t set_pwm_freq(struct device *dev, ··· 589 580 long val = simple_strtol(buf, NULL, 10); 590 581 591 582 mutex_lock(&data->update_lock); 592 - data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); 593 - lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), 594 - (data->zone[nr].range << 4) 595 - | data->pwm_freq[nr]); 583 + /* The ADT7468 has a special high-frequency PWM output mode, 584 + * where all PWM outputs are driven by a 22.5 kHz clock. 585 + * This might confuse the user, but there's not much we can do. */ 586 + if (data->type == adt7468 && val >= 11300) { /* High freq. mode */ 587 + data->cfg5 &= ~ADT7468_HFPWM; 588 + lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); 589 + } else { /* Low freq. mode */ 590 + data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); 591 + lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), 592 + (data->zone[nr].range << 4) 593 + | data->pwm_freq[nr]); 594 + if (data->type == adt7468) { 595 + data->cfg5 |= ADT7468_HFPWM; 596 + lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); 597 + } 598 + } 596 599 mutex_unlock(&data->update_lock); 597 600 return count; 598 601 }