vt1211.c

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

C
1,371
字号
	}	mutex_unlock(&data->update_lock);	return count;}/* --------------------------------------------------------------------- * Fan sysfs interfaces * ix = [0-1] * --------------------------------------------------------------------- */#define SHOW_FAN_INPUT		0#define SHOW_SET_FAN_MIN	1#define SHOW_SET_FAN_DIV	2#define SHOW_FAN_ALARM		3static ssize_t show_fan(struct device *dev, struct device_attribute *attr,			char *buf){	struct vt1211_data *data = vt1211_update_device(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	int res;	switch (fn) {	case SHOW_FAN_INPUT:		res = RPM_FROM_REG(data->fan[ix], data->fan_div[ix]);		break;	case SHOW_SET_FAN_MIN:		res = RPM_FROM_REG(data->fan_min[ix], data->fan_div[ix]);		break;	case SHOW_SET_FAN_DIV:		res = DIV_FROM_REG(data->fan_div[ix]);		break;	case SHOW_FAN_ALARM:		res = (data->alarms >> bitalarmfan[ix]) & 1;		break;	default:		res = 0;		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);	}	return sprintf(buf, "%d\n", res);}static ssize_t set_fan(struct device *dev, struct device_attribute *attr,		       const char *buf, size_t count){	struct vt1211_data *data = dev_get_drvdata(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	long val = simple_strtol(buf, NULL, 10);	int reg;	mutex_lock(&data->update_lock);	/* sync the data cache */	reg = vt1211_read8(data, VT1211_REG_FAN_DIV);	data->fan_div[0] = (reg >> 4) & 3;	data->fan_div[1] = (reg >> 6) & 3;	data->fan_ctl = reg & 0xf;	switch (fn) {	case SHOW_SET_FAN_MIN:		data->fan_min[ix] = RPM_TO_REG(val, data->fan_div[ix]);		vt1211_write8(data, VT1211_REG_FAN_MIN(ix),			      data->fan_min[ix]);		break;	case SHOW_SET_FAN_DIV:		switch (val) {			case 1: data->fan_div[ix] = 0; break;			case 2: data->fan_div[ix] = 1; break;			case 4: data->fan_div[ix] = 2; break;			case 8: data->fan_div[ix] = 3; break;			default:				count = -EINVAL;				dev_warn(dev, "fan div value %ld not "					 "supported. Choose one of 1, 2, "					 "4, or 8.\n", val);				goto EXIT;		}		vt1211_write8(data, VT1211_REG_FAN_DIV,			      ((data->fan_div[1] << 6) |			       (data->fan_div[0] << 4) |				data->fan_ctl));		break;	default:		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);	}EXIT:	mutex_unlock(&data->update_lock);	return count;}/* --------------------------------------------------------------------- * PWM sysfs interfaces * ix = [0-1] * --------------------------------------------------------------------- */#define SHOW_PWM			0#define SHOW_SET_PWM_ENABLE		1#define SHOW_SET_PWM_FREQ		2#define SHOW_SET_PWM_AUTO_CHANNELS_TEMP	3static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,			char *buf){	struct vt1211_data *data = vt1211_update_device(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	int res;	switch (fn) {	case SHOW_PWM:		res = data->pwm[ix];		break;	case SHOW_SET_PWM_ENABLE:		res = ((data->pwm_ctl[ix] >> 3) & 1) ? 2 : 0;		break;	case SHOW_SET_PWM_FREQ:		res = 90000 >> (data->pwm_clk & 7);		break;	case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:		res = (data->pwm_ctl[ix] & 7) + 1;		break;	default:		res = 0;		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);	}	return sprintf(buf, "%d\n", res);}static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,		       const char *buf, size_t count){	struct vt1211_data *data = dev_get_drvdata(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	long val = simple_strtol(buf, NULL, 10);	int tmp, reg;	mutex_lock(&data->update_lock);	switch (fn) {	case SHOW_SET_PWM_ENABLE:		/* sync the data cache */		reg = vt1211_read8(data, VT1211_REG_FAN_DIV);		data->fan_div[0] = (reg >> 4) & 3;		data->fan_div[1] = (reg >> 6) & 3;		data->fan_ctl = reg & 0xf;		reg = vt1211_read8(data, VT1211_REG_PWM_CTL);		data->pwm_ctl[0] = reg & 0xf;		data->pwm_ctl[1] = (reg >> 4) & 0xf;		switch (val) {		case 0:			data->pwm_ctl[ix] &= 7;			/* disable SmartGuardian if both PWM outputs are			 * disabled */			if ((data->pwm_ctl[ix ^ 1] & 1) == 0) {				data->fan_ctl &= 0xe;			}			break;		case 2:			data->pwm_ctl[ix] |= 8;			data->fan_ctl |= 1;			break;		default:			count = -EINVAL;			dev_warn(dev, "pwm mode %ld not supported. "				 "Choose one of 0 or 2.\n", val);			goto EXIT;		}		vt1211_write8(data, VT1211_REG_PWM_CTL,			      ((data->pwm_ctl[1] << 4) |				data->pwm_ctl[0]));		vt1211_write8(data, VT1211_REG_FAN_DIV,			      ((data->fan_div[1] << 6) |			       (data->fan_div[0] << 4) |				data->fan_ctl));		break;	case SHOW_SET_PWM_FREQ:		val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000);		/* calculate tmp = log2(val) */		tmp = 0;		for (val >>= 1; val > 0; val >>= 1) {			tmp++;		}		/* sync the data cache */		reg = vt1211_read8(data, VT1211_REG_PWM_CLK);		data->pwm_clk = (reg & 0xf8) | tmp;		vt1211_write8(data, VT1211_REG_PWM_CLK, data->pwm_clk);		break;	case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:		if ((val < 1) || (val > 7)) {			count = -EINVAL;			dev_warn(dev, "temp channel %ld not supported. "				 "Choose a value between 1 and 7.\n", val);			goto EXIT;		}		if (!ISTEMP(val - 1, data->uch_config)) {			count = -EINVAL;			dev_warn(dev, "temp channel %ld is not available.\n",				 val);			goto EXIT;		}		/* sync the data cache */		reg = vt1211_read8(data, VT1211_REG_PWM_CTL);		data->pwm_ctl[0] = reg & 0xf;		data->pwm_ctl[1] = (reg >> 4) & 0xf;		data->pwm_ctl[ix] = (data->pwm_ctl[ix] & 8) | (val - 1);		vt1211_write8(data, VT1211_REG_PWM_CTL,			      ((data->pwm_ctl[1] << 4) | data->pwm_ctl[0]));		break;	default:		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);	}EXIT:	mutex_unlock(&data->update_lock);	return count;}/* --------------------------------------------------------------------- * PWM auto point definitions * ix = [0-1] * ap = [0-3] * --------------------------------------------------------------------- *//* * pwm[ix+1]_auto_point[ap+1]_temp mapping table: * Note that there is only a single set of temp auto points that controls both * PWM controllers. We still create 2 sets of sysfs files to make it look * more consistent even though they map to the same registers. * * ix ap : description * ------------------- * 0  0  : pwm1/2 off temperature        (pwm_auto_temp[0]) * 0  1  : pwm1/2 low speed temperature  (pwm_auto_temp[1]) * 0  2  : pwm1/2 high speed temperature (pwm_auto_temp[2]) * 0  3  : pwm1/2 full speed temperature (pwm_auto_temp[3]) * 1  0  : pwm1/2 off temperature        (pwm_auto_temp[0]) * 1  1  : pwm1/2 low speed temperature  (pwm_auto_temp[1]) * 1  2  : pwm1/2 high speed temperature (pwm_auto_temp[2]) * 1  3  : pwm1/2 full speed temperature (pwm_auto_temp[3]) */static ssize_t show_pwm_auto_point_temp(struct device *dev,					struct device_attribute *attr,					char *buf){	struct vt1211_data *data = vt1211_update_device(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int ap = sensor_attr_2->nr;	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->pwm_ctl[ix] & 7,		       data->pwm_auto_temp[ap]));}static ssize_t set_pwm_auto_point_temp(struct device *dev,				       struct device_attribute *attr,				       const char *buf, size_t count){	struct vt1211_data *data = dev_get_drvdata(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int ap = sensor_attr_2->nr;	long val = simple_strtol(buf, NULL, 10);	int reg;	mutex_lock(&data->update_lock);	/* sync the data cache */	reg = vt1211_read8(data, VT1211_REG_PWM_CTL);	data->pwm_ctl[0] = reg & 0xf;	data->pwm_ctl[1] = (reg >> 4) & 0xf;	data->pwm_auto_temp[ap] = TEMP_TO_REG(data->pwm_ctl[ix] & 7, val);	vt1211_write8(data, VT1211_REG_PWM_AUTO_TEMP(ap),		      data->pwm_auto_temp[ap]);	mutex_unlock(&data->update_lock);	return count;}/* * pwm[ix+1]_auto_point[ap+1]_pwm mapping table: * Note that the PWM auto points 0 & 3 are hard-wired in the VT1211 and can't * be changed. * * ix ap : description * ------------------- * 0  0  : pwm1 off                   (pwm_auto_pwm[0][0], hard-wired to 0) * 0  1  : pwm1 low speed duty cycle  (pwm_auto_pwm[0][1]) * 0  2  : pwm1 high speed duty cycle (pwm_auto_pwm[0][2]) * 0  3  : pwm1 full speed            (pwm_auto_pwm[0][3], hard-wired to 255) * 1  0  : pwm2 off                   (pwm_auto_pwm[1][0], hard-wired to 0) * 1  1  : pwm2 low speed duty cycle  (pwm_auto_pwm[1][1]) * 1  2  : pwm2 high speed duty cycle (pwm_auto_pwm[1][2]) * 1  3  : pwm2 full speed            (pwm_auto_pwm[1][3], hard-wired to 255)*/static ssize_t show_pwm_auto_point_pwm(struct device *dev,				       struct device_attribute *attr,				       char *buf){	struct vt1211_data *data = vt1211_update_device(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int ap = sensor_attr_2->nr;	return sprintf(buf, "%d\n", data->pwm_auto_pwm[ix][ap]);}static ssize_t set_pwm_auto_point_pwm(struct device *dev,				      struct device_attribute *attr,				      const char *buf, size_t count){	struct vt1211_data *data = dev_get_drvdata(dev);	struct sensor_device_attribute_2 *sensor_attr_2 =						to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int ap = sensor_attr_2->nr;	long val = simple_strtol(buf, NULL, 10);	if ((val < 0) || (val > 255)) {		dev_err(dev, "pwm value %ld is out of range. "			"Choose a value between 0 and 255.\n" , val);		return -EINVAL;	}	mutex_lock(&data->update_lock);	data->pwm_auto_pwm[ix][ap] = val;	vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap),		      data->pwm_auto_pwm[ix][ap]);	mutex_unlock(&data->update_lock);	return count;}/* --------------------------------------------------------------------- * Miscellaneous sysfs interfaces (VRM, VID, name, and (legacy) alarms) * --------------------------------------------------------------------- */static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,			char *buf){	struct vt1211_data *data = dev_get_drvdata(dev);	return sprintf(buf, "%d\n", data->vrm);}static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,		       const char *buf, size_t count){	struct vt1211_data *data = dev_get_drvdata(dev);	long val = simple_strtol(buf, NULL, 10);	data->vrm = val;	return count;}static ssize_t show_vid(struct device *dev, struct device_attribute *attr,			char *buf){	struct vt1211_data *data = dev_get_drvdata(dev);	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));}static ssize_t show_name(struct device *dev,			 struct device_attribute *attr, char *buf){	struct vt1211_data *data = dev_get_drvdata(dev);	return sprintf(buf, "%s\n", data->name);}static ssize_t show_alarms(struct device *dev,			   struct device_attribute *attr, char *buf){	struct vt1211_data *data = vt1211_update_device(dev);	return sprintf(buf, "%d\n", data->alarms);}/* --------------------------------------------------------------------- * Device attribute structs * --------------------------------------------------------------------- */#define SENSOR_ATTR_IN_INPUT(ix) \	SENSOR_ATTR_2(in##ix##_input, S_IRUGO, \		show_in, NULL, SHOW_IN_INPUT, ix)static struct sensor_device_attribute_2 vt1211_sysfs_in_input[] = {	SENSOR_ATTR_IN_INPUT(0),	SENSOR_ATTR_IN_INPUT(1),	SENSOR_ATTR_IN_INPUT(2),	SENSOR_ATTR_IN_INPUT(3),	SENSOR_ATTR_IN_INPUT(4),	SENSOR_ATTR_IN_INPUT(5),};#define SENSOR_ATTR_IN_MIN(ix) \	SENSOR_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \		show_in, set_in, SHOW_SET_IN_MIN, ix)static struct sensor_device_attribute_2 vt1211_sysfs_in_min[] = {	SENSOR_ATTR_IN_MIN(0),	SENSOR_ATTR_IN_MIN(1),	SENSOR_ATTR_IN_MIN(2),	SENSOR_ATTR_IN_MIN(3),	SENSOR_ATTR_IN_MIN(4),	SENSOR_ATTR_IN_MIN(5),};#define SENSOR_ATTR_IN_MAX(ix) \	SENSOR_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \		show_in, set_in, SHOW_SET_IN_MAX, ix)static struct sensor_device_attribute_2 vt1211_sysfs_in_max[] = {	SENSOR_ATTR_IN_MAX(0),	SENSOR_ATTR_IN_MAX(1),	SENSOR_ATTR_IN_MAX(2),	SENSOR_ATTR_IN_MAX(3),	SENSOR_ATTR_IN_MAX(4),	SENSOR_ATTR_IN_MAX(5),};#define SENSOR_ATTR_IN_ALARM(ix) \	SENSOR_ATTR_2(in##ix##_alarm, S_IRUGO, \		show_in, NULL, SHOW_IN_ALARM, ix)static struct sensor_device_attribute_2 vt1211_sysfs_in_alarm[] = {	SENSOR_ATTR_IN_ALARM(0),	SENSOR_ATTR_IN_ALARM(1),	SENSOR_ATTR_IN_ALARM(2),	SENSOR_ATTR_IN_ALARM(3),	SENSOR_ATTR_IN_ALARM(4),	SENSOR_ATTR_IN_ALARM(5),};#define SENSOR_ATTR_TEMP_INPUT(ix) \

⌨️ 快捷键说明

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