lm93.c

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

C
2,063
字号
	/* <TODO> how to handle write errors? */	result = i2c_smbus_write_word_data(client, reg, value);	if (result < 0)		dev_warn(&client->dev,"lm93: write word data failed, "			 "0x%04x at address 0x%02x.\n", value, reg);	return result;}static u8 lm93_block_buffer[I2C_SMBUS_BLOCK_MAX];/*	read block data into values, retry if not expected length	fbn => index to lm93_block_read_cmds table		(Fixed Block Number - section 14.5.2 of LM93 datasheet)*/static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values){	int i, result=0;	for (i = 1; i <= MAX_RETRIES; i++) {		result = i2c_smbus_read_block_data(client,			lm93_block_read_cmds[fbn].cmd, lm93_block_buffer);		if (result == lm93_block_read_cmds[fbn].len) {			break;		} else {			dev_warn(&client->dev,"lm93: block read data failed, "				 "command 0x%02x.\n",				 lm93_block_read_cmds[fbn].cmd);			mdelay(i + 3);		}	}	if (result == lm93_block_read_cmds[fbn].len) {		memcpy(values,lm93_block_buffer,lm93_block_read_cmds[fbn].len);	} else {		/* <TODO> what to do in case of error? */	}}static struct lm93_data *lm93_update_device(struct device *dev){	struct i2c_client *client = to_i2c_client(dev);	struct lm93_data *data = i2c_get_clientdata(client);	const unsigned long interval = HZ + (HZ / 2);	mutex_lock(&data->update_lock);	if (time_after(jiffies, data->last_updated + interval) ||		!data->valid) {		data->update(data, client);		data->last_updated = jiffies;		data->valid = 1;	}	mutex_unlock(&data->update_lock);	return data;}/* update routine for data that has no corresponding SMBus block command */static void lm93_update_client_common(struct lm93_data *data,				      struct i2c_client *client){	int i;	u8 *ptr;	/* temp1 - temp4: limits */	for (i = 0; i < 4; i++) {		data->temp_lim[i].min =			lm93_read_byte(client, LM93_REG_TEMP_MIN(i));		data->temp_lim[i].max =			lm93_read_byte(client, LM93_REG_TEMP_MAX(i));	}	/* config register */	data->config = lm93_read_byte(client, LM93_REG_CONFIG);	/* vid1 - vid2: values */	for (i = 0; i < 2; i++)		data->vid[i] = lm93_read_byte(client, LM93_REG_VID(i));	/* prochot1 - prochot2: limits */	for (i = 0; i < 2; i++)		data->prochot_max[i] = lm93_read_byte(client,				LM93_REG_PROCHOT_MAX(i));	/* vccp1 - vccp2: VID relative limits */	for (i = 0; i < 2; i++)		data->vccp_limits[i] = lm93_read_byte(client,				LM93_REG_VCCP_LIMIT_OFF(i));	/* GPIO input state */	data->gpi = lm93_read_byte(client, LM93_REG_GPI);	/* #PROCHOT override state */	data->prochot_override = lm93_read_byte(client,			LM93_REG_PROCHOT_OVERRIDE);	/* #PROCHOT intervals */	data->prochot_interval = lm93_read_byte(client,			LM93_REG_PROCHOT_INTERVAL);	/* Fan Boost Termperature registers */	for (i = 0; i < 4; i++)		data->boost[i] = lm93_read_byte(client, LM93_REG_BOOST(i));	/* Fan Boost Temperature Hyst. registers */	data->boost_hyst[0] = lm93_read_byte(client, LM93_REG_BOOST_HYST_12);	data->boost_hyst[1] = lm93_read_byte(client, LM93_REG_BOOST_HYST_34);	/* Temperature Zone Min. PWM & Hysteresis registers */	data->auto_pwm_min_hyst[0] =			lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_12);	data->auto_pwm_min_hyst[1] =			lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_34);	/* #PROCHOT & #VRDHOT PWM Ramp Control register */	data->pwm_ramp_ctl = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL);	/* misc setup registers */	data->sfc1 = lm93_read_byte(client, LM93_REG_SFC1);	data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2);	data->sf_tach_to_pwm = lm93_read_byte(client,			LM93_REG_SF_TACH_TO_PWM);	/* write back alarm values to clear */	for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++)		lm93_write_byte(client, LM93_REG_HOST_ERROR_1 + i, *(ptr + i));}/* update routine which uses SMBus block data commands */static void lm93_update_client_full(struct lm93_data *data,				    struct i2c_client *client){	dev_dbg(&client->dev,"starting device update (block data enabled)\n");	/* in1 - in16: values & limits */	lm93_read_block(client, 3, (u8 *)(data->block3));	lm93_read_block(client, 7, (u8 *)(data->block7));	/* temp1 - temp4: values */	lm93_read_block(client, 2, (u8 *)(data->block2));	/* prochot1 - prochot2: values */	lm93_read_block(client, 4, (u8 *)(data->block4));	/* fan1 - fan4: values & limits */	lm93_read_block(client, 5, (u8 *)(data->block5));	lm93_read_block(client, 8, (u8 *)(data->block8));	/* pmw control registers */	lm93_read_block(client, 9, (u8 *)(data->block9));	/* alarm values */	lm93_read_block(client, 1, (u8 *)(&data->block1));	/* auto/pwm registers */	lm93_read_block(client, 10, (u8 *)(&data->block10));	lm93_update_client_common(data, client);}/* update routine which uses SMBus byte/word data commands only */static void lm93_update_client_min(struct lm93_data *data,				   struct i2c_client *client){	int i,j;	u8 *ptr;	dev_dbg(&client->dev,"starting device update (block data disabled)\n");	/* in1 - in16: values & limits */	for (i = 0; i < 16; i++) {		data->block3[i] =			lm93_read_byte(client, LM93_REG_IN(i));		data->block7[i].min =			lm93_read_byte(client, LM93_REG_IN_MIN(i));		data->block7[i].max =			lm93_read_byte(client, LM93_REG_IN_MAX(i));	}	/* temp1 - temp4: values */	for (i = 0; i < 4; i++) {		data->block2[i] =			lm93_read_byte(client, LM93_REG_TEMP(i));	}	/* prochot1 - prochot2: values */	for (i = 0; i < 2; i++) {		data->block4[i].cur =			lm93_read_byte(client, LM93_REG_PROCHOT_CUR(i));		data->block4[i].avg =			lm93_read_byte(client, LM93_REG_PROCHOT_AVG(i));	}	/* fan1 - fan4: values & limits */	for (i = 0; i < 4; i++) {		data->block5[i] =			lm93_read_word(client, LM93_REG_FAN(i));		data->block8[i] =			lm93_read_word(client, LM93_REG_FAN_MIN(i));	}	/* pwm control registers */	for (i = 0; i < 2; i++) {		for (j = 0; j < 4; j++) {			data->block9[i][j] =				lm93_read_byte(client, LM93_REG_PWM_CTL(i,j));		}	}	/* alarm values */	for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++) {		*(ptr + i) =			lm93_read_byte(client, LM93_REG_HOST_ERROR_1 + i);	}	/* auto/pwm (base temp) registers */	for (i = 0; i < 4; i++) {		data->block10.base[i] =			lm93_read_byte(client, LM93_REG_TEMP_BASE(i));	}	/* auto/pwm (offset temp) registers */	for (i = 0; i < 12; i++) {		data->block10.offset[i] =			lm93_read_byte(client, LM93_REG_TEMP_OFFSET(i));	}	lm93_update_client_common(data, client);}/* following are the sysfs callback functions */static ssize_t show_in(struct device *dev, struct device_attribute *attr,			char *buf){	int nr = (to_sensor_dev_attr(attr))->index;	struct lm93_data *data = lm93_update_device(dev);	return sprintf(buf, "%d\n", LM93_IN_FROM_REG(nr, data->block3[nr]));}static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 0);static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 1);static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 2);static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 3);static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 4);static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 5);static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 6);static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 7);static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in, NULL, 8);static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in, NULL, 9);static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_in, NULL, 10);static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_in, NULL, 11);static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_in, NULL, 12);static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_in, NULL, 13);static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_in, NULL, 14);static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in, NULL, 15);static ssize_t show_in_min(struct device *dev,			struct device_attribute *attr, char *buf){	int nr = (to_sensor_dev_attr(attr))->index;	struct lm93_data *data = lm93_update_device(dev);	int vccp = nr - 6;	long rc, vid;	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {		vid = LM93_VID_FROM_REG(data->vid[vccp]);		rc = LM93_IN_MIN_FROM_REG(data->vccp_limits[vccp], vid);	}	else {		rc = LM93_IN_FROM_REG(nr, data->block7[nr].min); \	}	return sprintf(buf, "%ld\n", rc); \}static ssize_t store_in_min(struct device *dev, struct device_attribute *attr,			    const char *buf, size_t count){	int nr = (to_sensor_dev_attr(attr))->index;	struct i2c_client *client = to_i2c_client(dev);	struct lm93_data *data = i2c_get_clientdata(client);	u32 val = simple_strtoul(buf, NULL, 10);	int vccp = nr - 6;	long vid;	mutex_lock(&data->update_lock);	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {		vid = LM93_VID_FROM_REG(data->vid[vccp]);		data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0xf0) |				LM93_IN_REL_TO_REG(val, 0, vid);		lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp),				data->vccp_limits[vccp]);	}	else {		data->block7[nr].min = LM93_IN_TO_REG(nr,val);		lm93_write_byte(client, LM93_REG_IN_MIN(nr),				data->block7[nr].min);	}	mutex_unlock(&data->update_lock);	return count;}static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 0);static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 1);static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 2);static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 3);static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 4);static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 5);static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 6);static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 7);static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 8);static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 9);static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 10);static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 11);static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 12);static SENSOR_DEVICE_ATTR(in14_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 13);static SENSOR_DEVICE_ATTR(in15_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 14);static SENSOR_DEVICE_ATTR(in16_min, S_IWUSR | S_IRUGO,			  show_in_min, store_in_min, 15);static ssize_t show_in_max(struct device *dev,			   struct device_attribute *attr, char *buf){	int nr = (to_sensor_dev_attr(attr))->index;	struct lm93_data *data = lm93_update_device(dev);	int vccp = nr - 6;	long rc, vid;	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {		vid = LM93_VID_FROM_REG(data->vid[vccp]);		rc = LM93_IN_MAX_FROM_REG(data->vccp_limits[vccp],vid);	}	else {		rc = LM93_IN_FROM_REG(nr,data->block7[nr].max); \	}	return sprintf(buf,"%ld\n",rc); \}static ssize_t store_in_max(struct device *dev, struct device_attribute *attr,			    const char *buf, size_t count){	int nr = (to_sensor_dev_attr(attr))->index;	struct i2c_client *client = to_i2c_client(dev);	struct lm93_data *data = i2c_get_clientdata(client);	u32 val = simple_strtoul(buf, NULL, 10);	int vccp = nr - 6;	long vid;	mutex_lock(&data->update_lock);	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {		vid = LM93_VID_FROM_REG(data->vid[vccp]);		data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0x0f) |				LM93_IN_REL_TO_REG(val, 1, vid);		lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp),				data->vccp_limits[vccp]);	}	else {		data->block7[nr].max = LM93_IN_TO_REG(nr,val);		lm93_write_byte(client, LM93_REG_IN_MAX(nr),				data->block7[nr].max);	}	mutex_unlock(&data->update_lock);	return count;}static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 0);static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 1);static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 2);static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 3);static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 4);static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 5);static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 6);static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 7);static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 8);static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 9);static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 10);static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 11);static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 12);static SENSOR_DEVICE_ATTR(in14_max, S_IWUSR | S_IRUGO,			  show_in_max, store_in_max, 13);

⌨️ 快捷键说明

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