Commit f6c61cff authored by Jean Delvare's avatar Jean Delvare Committed by Jean Delvare

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: default avatarJean Delvare <khali@linux-fr.org>
Cc: Darrick J. Wong <djwong@us.ibm.com>
Acked-by: default avatarGuenter Roeck <guenter.roeck@ericsson.com>
parent c36364db
...@@ -101,6 +101,13 @@ Devices has confirmed this "bug". The ADT7463 is reported to work as ...@@ -101,6 +101,13 @@ Devices has confirmed this "bug". The ADT7463 is reported to work as
described in the documentation. The current lm85 driver does not show the described in the documentation. The current lm85 driver does not show the
offset register. offset register.
The ADT7468 has a high-frequency PWM mode, where all PWM outputs are
driven by a 22.5 kHz clock. This is a global mode, not per-PWM output,
which means that setting any PWM frequency above 11.3 kHz will switch
all 3 PWM outputs to a 22.5 kHz frequency. Conversely, setting any PWM
frequency below 11.3 kHz will switch all 3 PWM outputs to a frequency
between 10 and 100 Hz, which can then be tuned separately.
See the vendor datasheets for more information. There is application note See the vendor datasheets for more information. There is application note
from National (AN-1260) with some additional information about the LM85. from National (AN-1260) with some additional information about the LM85.
The Analog Devices datasheet is very detailed and describes a procedure for The Analog Devices datasheet is very detailed and describes a procedure for
......
...@@ -64,9 +64,12 @@ enum chips { ...@@ -64,9 +64,12 @@ enum chips {
#define LM85_REG_VERSTEP 0x3f #define LM85_REG_VERSTEP 0x3f
#define ADT7468_REG_CFG5 0x7c #define ADT7468_REG_CFG5 0x7c
#define ADT7468_OFF64 0x01 #define ADT7468_OFF64 (1 << 0)
#define ADT7468_HFPWM (1 << 1)
#define IS_ADT7468_OFF64(data) \ #define IS_ADT7468_OFF64(data) \
((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64)) ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64))
#define IS_ADT7468_HFPWM(data) \
((data)->type == adt7468 && !((data)->cfg5 & ADT7468_HFPWM))
/* These are the recognized values for the above regs */ /* These are the recognized values for the above regs */
#define LM85_COMPANY_NATIONAL 0x01 #define LM85_COMPANY_NATIONAL 0x01
...@@ -567,8 +570,14 @@ static ssize_t show_pwm_freq(struct device *dev, ...@@ -567,8 +570,14 @@ static ssize_t show_pwm_freq(struct device *dev,
{ {
int nr = to_sensor_dev_attr(attr)->index; int nr = to_sensor_dev_attr(attr)->index;
struct lm85_data *data = lm85_update_device(dev); struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf, "%d\n", FREQ_FROM_REG(data->freq_map, int freq;
data->pwm_freq[nr]));
if (IS_ADT7468_HFPWM(data))
freq = 22500;
else
freq = FREQ_FROM_REG(data->freq_map, data->pwm_freq[nr]);
return sprintf(buf, "%d\n", freq);
} }
static ssize_t set_pwm_freq(struct device *dev, static ssize_t set_pwm_freq(struct device *dev,
...@@ -580,10 +589,22 @@ static ssize_t set_pwm_freq(struct device *dev, ...@@ -580,10 +589,22 @@ static ssize_t set_pwm_freq(struct device *dev,
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); /* The ADT7468 has a special high-frequency PWM output mode,
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), * where all PWM outputs are driven by a 22.5 kHz clock.
(data->zone[nr].range << 4) * This might confuse the user, but there's not much we can do. */
| data->pwm_freq[nr]); if (data->type == adt7468 && val >= 11300) { /* High freq. mode */
data->cfg5 &= ~ADT7468_HFPWM;
lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5);
} else { /* Low freq. mode */
data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val);
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
(data->zone[nr].range << 4)
| data->pwm_freq[nr]);
if (data->type == adt7468) {
data->cfg5 |= ADT7468_HFPWM;
lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5);
}
}
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment