Re: [PATCH 3/3] hwmon: (w83627ehf) Add support for the W83627UHG

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2011-10-31 at 10:23 -0400, Jean Delvare wrote:
> This is essentially a stripped down version of the W83627DHG. Noticeable
> difference is that it is still powered with +5V, as older models, even
> though the ADC resolution is 8 mV as newer models have.
> 
> Thanks to Ulf Bruman (Saab Group) for doing all the testing.
> 
> Signed-off-by: Jean Delvare <khali@xxxxxxxxxxxx>

Acked-by: Guenter Roeck <guenter.roeck@xxxxxxxxxxxx>

> ---
> Hmm, I'm almost certain that I had originally prepared changes to
> Kconfig and the documentation file too, but apparently they got lost
> somewhere. I'll see if I can find a backup somewhere.
> 
... assuming you'll add those.

Not sure if moving NCT677[56] to a separate driver would make much of a
difference in the complexity of this one.

Thanks,
Guenter

>  drivers/hwmon/w83627ehf.c |  146 +++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 121 insertions(+), 25 deletions(-)
> 
> --- linux-3.2-rc0.orig/drivers/hwmon/w83627ehf.c	2011-10-31 14:31:50.000000000 +0100
> +++ linux-3.2-rc0/drivers/hwmon/w83627ehf.c	2011-10-31 14:48:18.000000000 +0100
> @@ -39,6 +39,7 @@
>  					       0x8860 0xa1
>      w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
>      w83627dhg-p  9      5       4       3      0xb070 0xc1    0x5ca3
> +    w83627uhg    8      2       2       2      0xa230 0xc1    0x5ca3
>      w83667hg     9      5       3       3      0xa510 0xc1    0x5ca3
>      w83667hg-b   9      5       3       4      0xb350 0xc1    0x5ca3
>      nct6775f     9      4       3       9      0xb470 0xc1    0x5ca3
> @@ -61,14 +62,17 @@
>  #include <linux/io.h>
>  #include "lm75.h"
>  
> -enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b, nct6775,
> -	nct6776 };
> +enum kinds {
> +	w83627ehf, w83627dhg, w83627dhg_p, w83627uhg,
> +	w83667hg, w83667hg_b, nct6775, nct6776,
> +};
>  
>  /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
>  static const char * const w83627ehf_device_names[] = {
>  	"w83627ehf",
>  	"w83627dhg",
>  	"w83627dhg",
> +	"w83627uhg",
>  	"w83667hg",
>  	"w83667hg",
>  	"nct6775",
> @@ -104,6 +108,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable d
>  #define SIO_W83627EHG_ID	0x8860
>  #define SIO_W83627DHG_ID	0xa020
>  #define SIO_W83627DHG_P_ID	0xb070
> +#define SIO_W83627UHG_ID	0xa230
>  #define SIO_W83667HG_ID		0xa510
>  #define SIO_W83667HG_B_ID	0xb350
>  #define SIO_NCT6775_ID		0xb470
> @@ -388,18 +393,23 @@ div_from_reg(u8 reg)
>  	return 1 << reg;
>  }
>  
> -/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
> -
> -static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
> +/* Some of the voltage inputs have internal scaling, the tables below
> + * contain 8 (the ADC LSB in mV) * scaling factor * 100 */
> +static const u16 scale_in_common[10] = {
> +	800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800
> +};
> +static const u16 scale_in_w83627uhg[9] = {
> +	800, 800, 3328, 3424, 800, 800, 0, 3328, 3400
> +};
>  
> -static inline long in_from_reg(u8 reg, u8 nr)
> +static inline long in_from_reg(u8 reg, u8 nr, const u16 *scale_in)
>  {
> -	return reg * scale_in[nr];
> +	return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
>  }
>  
> -static inline u8 in_to_reg(u32 val, u8 nr)
> +static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scale_in)
>  {
> -	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0,
> +	return SENSORS_LIMIT(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0,
>  			     255);
>  }
>  
> @@ -430,6 +440,7 @@ struct w83627ehf_data {
>  	const u16 *REG_FAN_STOP_TIME;
>  	const u16 *REG_FAN_MAX_OUTPUT;
>  	const u16 *REG_FAN_STEP_OUTPUT;
> +	const u16 *scale_in;
>  
>  	unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
>  	unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
> @@ -481,7 +492,8 @@ struct w83627ehf_data {
>  	u8 vrm;
>  
>  	u16 have_temp;
> -	u8 in6_skip;
> +	u8 in6_skip:1;
> +	u8 temp3_val_only:1;
>  };
>  
>  struct w83627ehf_sio_data {
> @@ -907,7 +919,8 @@ show_##reg(struct device *dev, struct de
>  	struct sensor_device_attribute *sensor_attr = \
>  		to_sensor_dev_attr(attr); \
>  	int nr = sensor_attr->index; \
> -	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
> +	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr, \
> +		       data->scale_in)); \
>  }
>  show_in_reg(in)
>  show_in_reg(in_min)
> @@ -928,7 +941,7 @@ store_in_##reg(struct device *dev, struc
>  	if (err < 0) \
>  		return err; \
>  	mutex_lock(&data->update_lock); \
> -	data->in_##reg[nr] = in_to_reg(val, nr); \
> +	data->in_##reg[nr] = in_to_reg(val, nr, data->scale_in); \
>  	w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
>  			      data->in_##reg[nr]); \
>  	mutex_unlock(&data->update_lock); \
> @@ -1617,25 +1630,28 @@ static struct sensor_device_attribute sd
>  		    store_fan_step_output, 3),
>  };
>  
> +static struct sensor_device_attribute sda_sf3_arrays_fan3[] = {
> +	SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
> +		    store_fan_stop_time, 2),
> +	SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
> +		    store_fan_start_output, 2),
> +	SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
> +		    store_fan_stop_output, 2),
> +};
> +
>  static struct sensor_device_attribute sda_sf3_arrays[] = {
>  	SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
>  		    store_fan_stop_time, 0),
>  	SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
>  		    store_fan_stop_time, 1),
> -	SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
> -		    store_fan_stop_time, 2),
>  	SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
>  		    store_fan_start_output, 0),
>  	SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
>  		    store_fan_start_output, 1),
> -	SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
> -		    store_fan_start_output, 2),
>  	SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
>  		    store_fan_stop_output, 0),
>  	SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
>  		    store_fan_stop_output, 1),
> -	SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
> -		    store_fan_stop_output, 2),
>  };
>  
> 
> @@ -1728,6 +1744,8 @@ static void w83627ehf_device_remove_file
>  		    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
>  			device_remove_file(dev, &attr->dev_attr);
>  	}
> +	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++)
> +		device_remove_file(dev, &sda_sf3_arrays_fan3[i].dev_attr);
>  	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
>  		device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
>  	for (i = 0; i < data->in_num; i++) {
> @@ -1756,6 +1774,8 @@ static void w83627ehf_device_remove_file
>  			continue;
>  		device_remove_file(dev, &sda_temp_input[i].dev_attr);
>  		device_remove_file(dev, &sda_temp_label[i].dev_attr);
> +		if (i == 2 && data->temp3_val_only)
> +			continue;
>  		device_remove_file(dev, &sda_temp_max[i].dev_attr);
>  		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
>  		if (i > 2)
> @@ -1808,6 +1828,9 @@ static inline void __devinit w83627ehf_i
>  	case w83627ehf:
>  		diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
>  		break;
> +	case w83627uhg:
> +		diode = 0x00;
> +		break;
>  	default:
>  		diode = 0x70;
>  	}
> @@ -1871,6 +1894,13 @@ w83627ehf_check_fan_inputs(const struct
>  {
>  	int fan3pin, fan4pin, fan4min, fan5pin, regval;
>  
> +	/* The W83627UHG is simple, only two fan inputs, no config */
> +	if (sio_data->kind == w83627uhg) {
> +		data->has_fan = 0x03; /* fan1 and fan2 */
> +		data->has_fan_min = 0x03;
> +		return;
> +	}
> +
>  	superio_enter(sio_data->sioreg);
>  
>  	/* fan4 and fan5 share some pins with the GPIO and serial flash */
> @@ -1962,11 +1992,21 @@ static int __devinit w83627ehf_probe(str
>  
>  	/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
>  	data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
> -	/* 667HG, NCT6775F, and NCT6776F have 3 pwms */
> -	data->pwm_num = (sio_data->kind == w83667hg
> -			 || sio_data->kind == w83667hg_b
> -			 || sio_data->kind == nct6775
> -			 || sio_data->kind == nct6776) ? 3 : 4;
> +	/* 667HG, NCT6775F, and NCT6776F have 3 pwms, and 627UHG has only 2 */
> +	switch (sio_data->kind) {
> +	default:
> +		data->pwm_num = 4;
> +		break;
> +	case w83667hg:
> +	case w83667hg_b:
> +	case nct6775:
> +	case nct6776:
> +		data->pwm_num = 3;
> +		break;
> +	case w83627uhg:
> +		data->pwm_num = 2;
> +		break;
> +	}
>  
>  	/* Default to 3 temperature inputs, code below will adjust as needed */
>  	data->have_temp = 0x07;
> @@ -2085,6 +2125,42 @@ static int __devinit w83627ehf_probe(str
>  			data->in6_skip = 1;
>  
>  		data->temp_label = w83667hg_b_temp_label;
> +	} else if (sio_data->kind == w83627uhg) {
> +		u8 reg;
> +
> +		w83627ehf_set_temp_reg_ehf(data, 3);
> +
> +		/*
> +		 * Temperature sources for temp1 and temp2 are selected with
> +		 * bank 0, registers 0x49 and 0x4a.
> +		 */
> +		data->temp_src[0] = 0;	/* SYSTIN */
> +		reg = w83627ehf_read_value(data, 0x49) & 0x07;
> +		/* Adjust to have the same mapping as other source registers */
> +		if (reg == 0)
> +			data->temp_src[1]++;
> +		else if (reg >= 2 && reg <= 5)
> +			data->temp_src[1] += 2;
> +		else	/* should never happen */
> +			data->have_temp &= ~(1 << 1);
> +		reg = w83627ehf_read_value(data, 0x4a);
> +		data->temp_src[2] = reg >> 5;
> +
> +		/*
> +		 * Skip temp3 if source is invalid or the same as temp1
> +		 * or temp2.
> +		 */
> +		if (data->temp_src[2] == 2 || data->temp_src[2] == 3 ||
> +		    data->temp_src[2] == data->temp_src[0] ||
> +		    ((data->have_temp & (1 << 1)) &&
> +		     data->temp_src[2] == data->temp_src[1]))
> +			data->have_temp &= ~(1 << 2);
> +		else
> +			data->temp3_val_only = 1;	/* No limit regs */
> +
> +		data->in6_skip = 1;			/* No VIN3 */
> +
> +		data->temp_label = w83667hg_b_temp_label;
>  	} else {
>  		w83627ehf_set_temp_reg_ehf(data, 3);
>  
> @@ -2162,6 +2238,12 @@ static int __devinit w83627ehf_probe(str
>  		  W83627EHF_REG_FAN_STEP_OUTPUT_COMMON;
>  	}
>  
> +	/* Setup input voltage scaling factors */
> +	if (sio_data->kind == w83627uhg)
> +		data->scale_in = scale_in_w83627uhg;
> +	else
> +		data->scale_in = scale_in_common;
> +
>  	/* Initialize the chip */
>  	w83627ehf_init_device(data, sio_data->kind);
>  
> @@ -2178,7 +2260,7 @@ static int __devinit w83627ehf_probe(str
>  		err = device_create_file(dev, &dev_attr_cpu0_vid);
>  		if (err)
>  			goto exit_release;
> -	} else {
> +	} else if (sio_data->kind != w83627uhg) {
>  		superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
>  		if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
>  			/* Set VID input sensibility if needed. In theory the
> @@ -2268,7 +2350,14 @@ static int __devinit w83627ehf_probe(str
>  				goto exit_remove;
>  		}
>  	}
> -	/* if fan4 is enabled create the sf3 files for it */
> +	/* if fan3 and fan4 are enabled create the sf3 files for them */
> +	if ((data->has_fan & (1 << 2)) && data->pwm_num >= 3)
> +		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++) {
> +			err = device_create_file(dev,
> +					&sda_sf3_arrays_fan3[i].dev_attr);
> +			if (err)
> +				goto exit_remove;
> +		}
>  	if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
>  		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
>  			err = device_create_file(dev,
> @@ -2336,6 +2425,8 @@ static int __devinit w83627ehf_probe(str
>  			if (err)
>  				goto exit_remove;
>  		}
> +		if (i == 2 && data->temp3_val_only)
> +			continue;
>  		if (data->reg_temp_over[i]) {
>  			err = device_create_file(dev,
>  				&sda_temp_max[i].dev_attr);
> @@ -2419,6 +2510,7 @@ static int __init w83627ehf_find(int sio
>  	static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
>  	static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
>  	static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
> +	static const char __initdata sio_name_W83627UHG[] = "W83627UHG";
>  	static const char __initdata sio_name_W83667HG[] = "W83667HG";
>  	static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
>  	static const char __initdata sio_name_NCT6775[] = "NCT6775F";
> @@ -2451,6 +2543,10 @@ static int __init w83627ehf_find(int sio
>  		sio_data->kind = w83627dhg_p;
>  		sio_name = sio_name_W83627DHG_P;
>  		break;
> +	case SIO_W83627UHG_ID:
> +		sio_data->kind = w83627uhg;
> +		sio_name = sio_name_W83627UHG;
> +		break;
>  	case SIO_W83667HG_ID:
>  		sio_data->kind = w83667hg;
>  		sio_name = sio_name_W83667HG;
> 
> 



_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors


[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux