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>
This commit is contained in:
Jean Delvare 2010-10-28 20:31:50 +02:00 committed by Jean Delvare
parent c36364dbf3
commit f6c61cff8b
2 changed files with 35 additions and 7 deletions

View File

@ -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

View File

@ -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,
{ {
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,
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;
} }