lkml.org 
[lkml]   [2011]   [Mar]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 04/11] hwmon: (w83627ehf) Improve support for W83667HG-B
    Date
    Add support for 4th temperature sensor on W83677HG-B.
    Display temperature labels on W83677HG-B to report temperature sources.

    Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
    ---
    Documentation/hwmon/w83627ehf | 19 +++--
    drivers/hwmon/w83627ehf.c | 155 ++++++++++++++++++++++++++++++++--------
    2 files changed, 136 insertions(+), 38 deletions(-)

    diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
    index 13d5561..0643019 100644
    --- a/Documentation/hwmon/w83627ehf
    +++ b/Documentation/hwmon/w83627ehf
    @@ -39,16 +39,21 @@ This driver implements support for the Winbond W83627EHF, W83627EHG,
    W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips.
    We will refer to them collectively as Winbond chips.

    -The chips implement three temperature sensors, five fan rotation
    -speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
    -VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG and 667HG), alarms
    -with beep warnings (control unimplemented), and some automatic fan
    +The chips implement three temperature sensors (up to four for 667HG-B),
    +five fan rotation speed sensors, ten analog voltage sensors (only nine for the
    +627DHG), one VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG and 667HG),
    +alarms with beep warnings (control unimplemented), and some automatic fan
    regulation strategies (plus manual fan control mode).

    +The temperature sensor sources on W82677HG-B are configurable. temp4 is only
    +reported if its temperature source differs from the temperature sources of the
    +other three temperature sensors. The configured source for each of the
    +temperature sensors is reported in tempX_label.
    +
    Temperatures are measured in degrees Celsius and measurement resolution is 1
    -degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
    -the temperature gets higher than high limit; it stays on until the temperature
    -falls below the hysteresis value.
    +degC for temp1 and temp4, and 0.5 degC for temp2 and temp3. An alarm is
    +triggered when the temperature gets higher than high limit; it stays on until
    +the temperature falls below the hysteresis value.

    Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
    triggered if the rotation speed has dropped below a programmable limit. Fan
    diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
    index 5a627b9..d10fe70 100644
    --- a/drivers/hwmon/w83627ehf.c
    +++ b/drivers/hwmon/w83627ehf.c
    @@ -39,7 +39,7 @@
    w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3
    w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3
    w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3
    - w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3
    + w83667hg-b 9 5 3 4 0xb350 0xc1 0x5ca3
    */

    #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
    @@ -164,10 +164,10 @@ static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
    #define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
    (0x550 + (nr) - 7))

    -static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250 };
    -static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253 };
    -static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255 };
    -static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252 };
    +static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250, 0x7e };
    +static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253, 0 };
    +static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255, 0 };
    +static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 };

    /* Fan clock dividers are spread over the following five registers */
    #define W83627EHF_REG_FANDIV1 0x47
    @@ -213,6 +213,19 @@ static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
    static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
    static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c };

    +static const char *const w83667hg_b_temp_label[] = {
    + "SYSTIN",
    + "CPUTIN",
    + "AUXTIN",
    + "AMDTSI",
    + "PECI Agent 1",
    + "PECI Agent 2",
    + "PECI Agent 3",
    + "PECI Agent 4"
    +};
    +
    +#define NUM_REG_TEMP 4
    +
    static inline int is_word_sized(u16 reg)
    {
    return (((reg & 0xff00) == 0x100
    @@ -294,6 +307,9 @@ struct w83627ehf_data {
    struct device *hwmon_dev;
    struct mutex lock;

    + u8 temp_src[NUM_REG_TEMP];
    + const char * const *temp_label;
    +
    const u8 *REG_FAN_START_OUTPUT;
    const u8 *REG_FAN_STOP_OUTPUT;
    const u8 *REG_FAN_MAX_OUTPUT;
    @@ -314,9 +330,9 @@ struct w83627ehf_data {
    u8 fan_div[5];
    u8 has_fan; /* some fan inputs can be disabled */
    u8 temp_type[3];
    - s16 temp[3];
    - s16 temp_max[3];
    - s16 temp_max_hyst[3];
    + s16 temp[4];
    + s16 temp_max[4];
    + s16 temp_max_hyst[4];
    u32 alarms;

    u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
    @@ -339,7 +355,7 @@ struct w83627ehf_data {
    u8 vid;
    u8 vrm;

    - u8 temp3_disable;
    + u8 have_temp;
    u8 in6_skip;
    };

    @@ -577,12 +593,18 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
    }

    /* Measured temperatures and limits */
    - for (i = 0; i < 3; i++) {
    - data->temp[i] = w83627ehf_read_value(data,
    - W83627EHF_REG_TEMP[i]);
    - data->temp_max[i] = w83627ehf_read_value(data,
    - W83627EHF_REG_TEMP_OVER[i]);
    - data->temp_max_hyst[i] = w83627ehf_read_value(data,
    + for (i = 0; i < NUM_REG_TEMP; i++) {
    + if (!(data->have_temp & (1 << i)))
    + continue;
    + data->temp[i]
    + = w83627ehf_read_value(data, W83627EHF_REG_TEMP[i]);
    + if (i > 2)
    + break;
    + data->temp_max[i]
    + = w83627ehf_read_value(data,
    + W83627EHF_REG_TEMP_OVER[i]);
    + data->temp_max_hyst[i]
    + = w83627ehf_read_value(data,
    W83627EHF_REG_TEMP_HYST[i]);
    }

    @@ -844,6 +866,15 @@ static struct sensor_device_attribute sda_fan_div[] = {
    SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
    };

    +static ssize_t
    +show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
    +{
    + struct w83627ehf_data *data = w83627ehf_update_device(dev);
    + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
    + int nr = sensor_attr->index;
    + return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
    +}
    +
    #define show_temp_reg(REG, reg) \
    static ssize_t \
    show_##reg(struct device *dev, struct device_attribute *attr, \
    @@ -897,6 +928,14 @@ static struct sensor_device_attribute sda_temp_input[] = {
    SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
    SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
    SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
    + SENSOR_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3),
    +};
    +
    +static struct sensor_device_attribute sda_temp_label[] = {
    + SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
    + SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
    + SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
    + SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
    };

    static struct sensor_device_attribute sda_temp_max[] = {
    @@ -1328,10 +1367,13 @@ static void w83627ehf_device_remove_files(struct device *dev)
    device_remove_file(dev, &sda_target_temp[i].dev_attr);
    device_remove_file(dev, &sda_tolerance[i].dev_attr);
    }
    - for (i = 0; i < 3; i++) {
    - if ((i == 2) && data->temp3_disable)
    + for (i = 0; i < NUM_REG_TEMP; i++) {
    + if (!(data->have_temp & (1 << i)))
    continue;
    device_remove_file(dev, &sda_temp_input[i].dev_attr);
    + device_remove_file(dev, &sda_temp_label[i].dev_attr);
    + if (i > 2)
    + break;
    device_remove_file(dev, &sda_temp_max[i].dev_attr);
    device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
    device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
    @@ -1354,12 +1396,14 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data)
    w83627ehf_write_value(data, W83627EHF_REG_CONFIG,
    tmp | 0x01);

    - /* Enable temp2 and temp3 if needed */
    - for (i = 1; i < 3; i++) {
    + /* Enable temperature sensors if needed */
    + for (i = 0; i < NUM_REG_TEMP; i++) {
    + if (!(data->have_temp & (1 << i)))
    + continue;
    + if (!W83627EHF_REG_TEMP_CONFIG[i])
    + continue;
    tmp = w83627ehf_read_value(data,
    W83627EHF_REG_TEMP_CONFIG[i]);
    - if ((i == 2) && data->temp3_disable)
    - continue;
    if (tmp & 0x01)
    w83627ehf_write_value(data,
    W83627EHF_REG_TEMP_CONFIG[i],
    @@ -1417,11 +1461,52 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
    data->pwm_num = (sio_data->kind == w83667hg
    || sio_data->kind == w83667hg_b) ? 3 : 4;

    + data->have_temp = 0x07;
    /* Check temp3 configuration bit for 667HG */
    - if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
    - data->temp3_disable = w83627ehf_read_value(data,
    - W83627EHF_REG_TEMP_CONFIG[2]) & 0x01;
    - data->in6_skip = !data->temp3_disable;
    + if (sio_data->kind == w83667hg) {
    + u8 reg;
    +
    + reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
    + if (reg & 0x01)
    + data->have_temp &= ~(1 << 2);
    + else
    + data->in6_skip = 1; /* Either temp3 or in6 */
    + } else if (sio_data->kind == w83667hg_b) {
    + u8 reg;
    +
    + reg = w83627ehf_read_value(data, 0x4a);
    + data->temp_src[0] = reg >> 5;
    + reg = w83627ehf_read_value(data, 0x49);
    + data->temp_src[1] = reg & 0x07;
    + data->temp_src[2] = (reg >> 4) & 0x07;
    +
    + /*
    + * W83667HG-B has another temperature register at 0x7e.
    + * The temperature source is selected with register 0x7d.
    + * Support it if the source differs from already reported
    + * sources.
    + */
    + reg = w83627ehf_read_value(data, 0x7d);
    + reg &= 0x07;
    + if (reg != data->temp_src[0] && reg != data->temp_src[1]
    + && reg != data->temp_src[2]) {
    + data->temp_src[3] = reg;
    + data->have_temp |= 1 << 3;
    + }
    +
    + /*
    + * Chip supports either AUXTIN or VIN3. Try to find out which
    + * one.
    + */
    + reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
    + if (data->temp_src[2] == 2 && (reg & 0x01))
    + data->have_temp &= ~(1 << 2);
    +
    + if ((data->temp_src[2] == 2 && (data->have_temp & (1 << 2)))
    + || (data->temp_src[3] == 2 && (data->have_temp & (1 << 3))))
    + data->in6_skip = 1;
    +
    + data->temp_label = w83667hg_b_temp_label;
    }

    data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
    @@ -1584,13 +1669,21 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
    }
    }

    - for (i = 0; i < 3; i++) {
    - if ((i == 2) && data->temp3_disable)
    + for (i = 0; i < NUM_REG_TEMP; i++) {
    + if (!(data->have_temp & (1 << i)))
    continue;
    - if ((err = device_create_file(dev,
    - &sda_temp_input[i].dev_attr))
    - || (err = device_create_file(dev,
    - &sda_temp_max[i].dev_attr))
    + err = device_create_file(dev, &sda_temp_input[i].dev_attr);
    + if (err)
    + goto exit_remove;
    + if (data->temp_label) {
    + err = device_create_file(dev,
    + &sda_temp_label[i].dev_attr);
    + if (err)
    + goto exit_remove;
    + }
    + if (i > 2)
    + break;
    + if ((err = device_create_file(dev, &sda_temp_max[i].dev_attr))
    || (err = device_create_file(dev,
    &sda_temp_max_hyst[i].dev_attr))
    || (err = device_create_file(dev,
    --
    1.7.3.1


    \
     
     \ /
      Last update: 2011-03-06 11:19    [W:0.040 / U:272.284 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site