w83627ehf.c

来自「linux 内核源代码」· C语言 代码 · 共 1,579 行 · 第 1/4 页

C
1,579
字号
		break;	case 2:		reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV2) & 0x3f)		    | ((data->fan_div[2] & 0x03) << 6);		w83627ehf_write_value(data, W83627EHF_REG_FANDIV2, reg);		reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0x7f)		    | ((data->fan_div[2] & 0x04) << 5);		w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg);		break;	case 3:		reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0xfc)		    | (data->fan_div[3] & 0x03);		w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg);		reg = (w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT) & 0x7f)		    | ((data->fan_div[3] & 0x04) << 5);		w83627ehf_write_value(data, W83627EHF_REG_SMI_OVT, reg);		break;	case 4:		reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0x73)		    | ((data->fan_div[4] & 0x03) << 2)		    | ((data->fan_div[4] & 0x04) << 5);		w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg);		break;	}}static void w83627ehf_update_fan_div(struct w83627ehf_data *data){	int i;	i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);	data->fan_div[0] = (i >> 4) & 0x03;	data->fan_div[1] = (i >> 6) & 0x03;	i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV2);	data->fan_div[2] = (i >> 6) & 0x03;	i = w83627ehf_read_value(data, W83627EHF_REG_VBAT);	data->fan_div[0] |= (i >> 3) & 0x04;	data->fan_div[1] |= (i >> 4) & 0x04;	data->fan_div[2] |= (i >> 5) & 0x04;	if (data->has_fan & ((1 << 3) | (1 << 4))) {		i = w83627ehf_read_value(data, W83627EHF_REG_DIODE);		data->fan_div[3] = i & 0x03;		data->fan_div[4] = ((i >> 2) & 0x03)				 | ((i >> 5) & 0x04);	}	if (data->has_fan & (1 << 3)) {		i = w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT);		data->fan_div[3] |= (i >> 5) & 0x04;	}}static struct w83627ehf_data *w83627ehf_update_device(struct device *dev){	struct w83627ehf_data *data = dev_get_drvdata(dev);	int pwmcfg = 0, tolerance = 0; /* shut up the compiler */	int i;	mutex_lock(&data->update_lock);	if (time_after(jiffies, data->last_updated + HZ + HZ/2)	 || !data->valid) {		/* Fan clock dividers */		w83627ehf_update_fan_div(data);		/* Measured voltages and limits */		for (i = 0; i < data->in_num; i++) {			data->in[i] = w83627ehf_read_value(data,				      W83627EHF_REG_IN(i));			data->in_min[i] = w83627ehf_read_value(data,					  W83627EHF_REG_IN_MIN(i));			data->in_max[i] = w83627ehf_read_value(data,					  W83627EHF_REG_IN_MAX(i));		}		/* Measured fan speeds and limits */		for (i = 0; i < 5; i++) {			if (!(data->has_fan & (1 << i)))				continue;			data->fan[i] = w83627ehf_read_value(data,				       W83627EHF_REG_FAN[i]);			data->fan_min[i] = w83627ehf_read_value(data,					   W83627EHF_REG_FAN_MIN[i]);			/* If we failed to measure the fan speed and clock			   divider can be increased, let's try that for next			   time */			if (data->fan[i] == 0xff			 && data->fan_div[i] < 0x07) {			 	dev_dbg(dev, "Increasing fan%d "					"clock divider from %u to %u\n",					i + 1, div_from_reg(data->fan_div[i]),					div_from_reg(data->fan_div[i] + 1));				data->fan_div[i]++;				w83627ehf_write_fan_div(data, i);				/* Preserve min limit if possible */				if (data->fan_min[i] >= 2				 && data->fan_min[i] != 255)					w83627ehf_write_value(data,						W83627EHF_REG_FAN_MIN[i],						(data->fan_min[i] /= 2));			}		}		for (i = 0; i < 4; i++) {			/* pwmcfg, tolarance mapped for i=0, i=1 to same reg */			if (i != 1) {				pwmcfg = w83627ehf_read_value(data,						W83627EHF_REG_PWM_ENABLE[i]);				tolerance = w83627ehf_read_value(data,						W83627EHF_REG_TOLERANCE[i]);			}			data->pwm_mode[i] =				((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)				? 0 : 1;			data->pwm_enable[i] =					((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])						& 3) + 1;			data->pwm[i] = w83627ehf_read_value(data,						W83627EHF_REG_PWM[i]);			data->fan_min_output[i] = w83627ehf_read_value(data,						W83627EHF_REG_FAN_MIN_OUTPUT[i]);			data->fan_stop_time[i] = w83627ehf_read_value(data,						W83627EHF_REG_FAN_STOP_TIME[i]);			data->target_temp[i] =				w83627ehf_read_value(data,					W83627EHF_REG_TARGET[i]) &					(data->pwm_mode[i] == 1 ? 0x7f : 0xff);			data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))									& 0x0f;		}		/* Measured temperatures and limits */		data->temp1 = w83627ehf_read_value(data,			      W83627EHF_REG_TEMP1);		data->temp1_max = w83627ehf_read_value(data,				  W83627EHF_REG_TEMP1_OVER);		data->temp1_max_hyst = w83627ehf_read_value(data,				       W83627EHF_REG_TEMP1_HYST);		for (i = 0; i < 2; 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,						 W83627EHF_REG_TEMP_HYST[i]);		}		data->alarms = w83627ehf_read_value(data,					W83627EHF_REG_ALARM1) |			       (w83627ehf_read_value(data,					W83627EHF_REG_ALARM2) << 8) |			       (w83627ehf_read_value(data,					W83627EHF_REG_ALARM3) << 16);		data->last_updated = jiffies;		data->valid = 1;	}	mutex_unlock(&data->update_lock);	return data;}/* * Sysfs callback functions */#define show_in_reg(reg) \static ssize_t \show_##reg(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, "%ld\n", in_from_reg(data->reg[nr], nr)); \}show_in_reg(in)show_in_reg(in_min)show_in_reg(in_max)#define store_in_reg(REG, reg) \static ssize_t \store_in_##reg (struct device *dev, struct device_attribute *attr, \			const char *buf, size_t count) \{ \	struct w83627ehf_data *data = dev_get_drvdata(dev); \	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \	int nr = sensor_attr->index; \	u32 val = simple_strtoul(buf, NULL, 10); \ \	mutex_lock(&data->update_lock); \	data->in_##reg[nr] = in_to_reg(val, nr); \	w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \			      data->in_##reg[nr]); \	mutex_unlock(&data->update_lock); \	return count; \}store_in_reg(MIN, min)store_in_reg(MAX, max)static ssize_t show_alarm(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, "%u\n", (data->alarms >> nr) & 0x01);}static struct sensor_device_attribute sda_in_input[] = {	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),	SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),	SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),};static struct sensor_device_attribute sda_in_alarm[] = {	SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),	SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),	SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),	SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),	SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),	SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21),	SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20),	SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16),	SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17),	SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19),};static struct sensor_device_attribute sda_in_min[] = {       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),       SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),};static struct sensor_device_attribute sda_in_max[] = {       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),       SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),};#define show_fan_reg(reg) \static ssize_t \show_##reg(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, "%d\n", \		       fan_from_reg(data->reg[nr], \				    div_from_reg(data->fan_div[nr]))); \}show_fan_reg(fan);show_fan_reg(fan_min);static ssize_tshow_fan_div(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, "%u\n", div_from_reg(data->fan_div[nr]));}static ssize_tstore_fan_min(struct device *dev, struct device_attribute *attr,	      const char *buf, size_t count){	struct w83627ehf_data *data = dev_get_drvdata(dev);	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);	int nr = sensor_attr->index;	unsigned int val = simple_strtoul(buf, NULL, 10);	unsigned int reg;	u8 new_div;	mutex_lock(&data->update_lock);	if (!val) {		/* No min limit, alarm disabled */		data->fan_min[nr] = 255;		new_div = data->fan_div[nr]; /* No change */		dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);	} else if ((reg = 1350000U / val) >= 128 * 255) {		/* Speed below this value cannot possibly be represented,		   even with the highest divider (128) */		data->fan_min[nr] = 254;		new_div = 7; /* 128 == (1 << 7) */		dev_warn(dev, "fan%u low limit %u below minimum %u, set to "			 "minimum\n", nr + 1, val, fan_from_reg(254, 128));	} else if (!reg) {		/* Speed above this value cannot possibly be represented,		   even with the lowest divider (1) */		data->fan_min[nr] = 1;		new_div = 0; /* 1 == (1 << 0) */		dev_warn(dev, "fan%u low limit %u above maximum %u, set to "			 "maximum\n", nr + 1, val, fan_from_reg(1, 1));	} else {		/* Automatically pick the best divider, i.e. the one such		   that the min limit will correspond to a register value		   in the 96..192 range */		new_div = 0;		while (reg > 192 && new_div < 7) {			reg >>= 1;			new_div++;		}		data->fan_min[nr] = reg;	}	/* Write both the fan clock divider (if it changed) and the new	   fan min (unconditionally) */	if (new_div != data->fan_div[nr]) {		/* Preserve the fan speed reading */		if (data->fan[nr] != 0xff) {			if (new_div > data->fan_div[nr])				data->fan[nr] >>= new_div - data->fan_div[nr];			else if (data->fan[nr] & 0x80)				data->fan[nr] = 0xff;			else				data->fan[nr] <<= data->fan_div[nr] - new_div;		}		dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",			nr + 1, div_from_reg(data->fan_div[nr]),			div_from_reg(new_div));		data->fan_div[nr] = new_div;		w83627ehf_write_fan_div(data, nr);		/* Give the chip time to sample a new speed value */		data->last_updated = jiffies;	}	w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[nr],			      data->fan_min[nr]);	mutex_unlock(&data->update_lock);	return count;}static struct sensor_device_attribute sda_fan_input[] = {	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),	SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),};static struct sensor_device_attribute sda_fan_alarm[] = {	SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),	SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),	SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),	SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10),	SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23),};static struct sensor_device_attribute sda_fan_min[] = {	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,		    store_fan_min, 0),	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,		    store_fan_min, 1),	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,		    store_fan_min, 2),	SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,		    store_fan_min, 3),	SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,		    store_fan_min, 4),};static struct sensor_device_attribute sda_fan_div[] = {	SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),	SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),	SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),	SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),	SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),};#define show_temp1_reg(reg) \

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?