⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fscher.c

📁 i2c 的 驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	data->valid = 0;	init_MUTEX(&data->update_lock);	/* Tell the I2C layer a new client has arrived */	if ((err = i2c_attach_client(new_client)))		goto exit_free;	fscher_init_client(new_client);	/* Register sysfs hooks */	device_create_file_revision(new_client);	device_create_file_alarms(new_client);	device_create_file_control(new_client);	device_create_file_watchdog(new_client);	device_create_file_in(new_client, 0);	device_create_file_in(new_client, 1);	device_create_file_in(new_client, 2);	device_create_file_fan(new_client, 1);	device_create_file_fan(new_client, 2);	device_create_file_fan(new_client, 3);	device_create_file_temp(new_client, 1);	device_create_file_temp(new_client, 2);	device_create_file_temp(new_client, 3);	return 0;exit_free:	kfree(data);exit:	return err;}static int fscher_detach_client(struct i2c_client *client){	int err;	if ((err = i2c_detach_client(client))) {		dev_err(&client->dev, "Client deregistration failed, "			"client not detached.\n");		return err;	}	kfree(i2c_get_clientdata(client));	return 0;}static int fscher_read_value(struct i2c_client *client, u8 reg){	dev_dbg(&client->dev, "read reg 0x%02x\n", reg);	return i2c_smbus_read_byte_data(client, reg);}static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value){	dev_dbg(&client->dev, "write reg 0x%02x, val 0x%02x\n",		reg, value);	return i2c_smbus_write_byte_data(client, reg, value);}/* Called when we have found a new FSC Hermes. */static void fscher_init_client(struct i2c_client *client){	struct fscher_data *data = i2c_get_clientdata(client);	/* Read revision from chip */	data->revision =  fscher_read_value(client, FSCHER_REG_REVISION);}static struct fscher_data *fscher_update_device(struct device *dev){	struct i2c_client *client = to_i2c_client(dev);	struct fscher_data *data = i2c_get_clientdata(client);	down(&data->update_lock);	if ((jiffies - data->last_updated > 2 * HZ) ||	    (jiffies < data->last_updated) || !data->valid) {		dev_dbg(&client->dev, "Starting fscher update\n");		data->temp_act[0] = fscher_read_value(client, FSCHER_REG_TEMP0_ACT);		data->temp_act[1] = fscher_read_value(client, FSCHER_REG_TEMP1_ACT);		data->temp_act[2] = fscher_read_value(client, FSCHER_REG_TEMP2_ACT);		data->temp_status[0] = fscher_read_value(client, FSCHER_REG_TEMP0_STATE);		data->temp_status[1] = fscher_read_value(client, FSCHER_REG_TEMP1_STATE);		data->temp_status[2] = fscher_read_value(client, FSCHER_REG_TEMP2_STATE);		data->volt[0] = fscher_read_value(client, FSCHER_REG_VOLT_12);		data->volt[1] = fscher_read_value(client, FSCHER_REG_VOLT_5);		data->volt[2] = fscher_read_value(client, FSCHER_REG_VOLT_BATT);		data->fan_act[0] = fscher_read_value(client, FSCHER_REG_FAN0_ACT);		data->fan_act[1] = fscher_read_value(client, FSCHER_REG_FAN1_ACT);		data->fan_act[2] = fscher_read_value(client, FSCHER_REG_FAN2_ACT);		data->fan_status[0] = fscher_read_value(client, FSCHER_REG_FAN0_STATE);		data->fan_status[1] = fscher_read_value(client, FSCHER_REG_FAN1_STATE);		data->fan_status[2] = fscher_read_value(client, FSCHER_REG_FAN2_STATE);		data->fan_min[0] = fscher_read_value(client, FSCHER_REG_FAN0_MIN);		data->fan_min[1] = fscher_read_value(client, FSCHER_REG_FAN1_MIN);		data->fan_min[2] = fscher_read_value(client, FSCHER_REG_FAN2_MIN);		data->fan_ripple[0] = fscher_read_value(client, FSCHER_REG_FAN0_RIPPLE);		data->fan_ripple[1] = fscher_read_value(client, FSCHER_REG_FAN1_RIPPLE);		data->fan_ripple[2] = fscher_read_value(client, FSCHER_REG_FAN2_RIPPLE);		data->watchdog[0] = fscher_read_value(client, FSCHER_REG_WDOG_PRESET);		data->watchdog[1] = fscher_read_value(client, FSCHER_REG_WDOG_STATE);		data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL);		data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE);		data->last_updated = jiffies;		data->valid = 1;                 	}	up(&data->update_lock);	return data;}#define FAN_INDEX_FROM_NUM(nr)	((nr) - 1)static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *data,			      const char *buf, size_t count, int nr, int reg){	/* bits 0..1, 3..7 reserved => mask with 0x04 */  	unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04;	data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v;	fscher_write_value(client, reg, v);	return count;}static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr){	/* bits 0..1, 3..7 reserved => mask with 0x04 */  	return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04);}static ssize_t set_fan_pwm(struct i2c_client *client, struct fscher_data *data,		       const char *buf, size_t count, int nr, int reg){	data->fan_min[FAN_INDEX_FROM_NUM(nr)] = simple_strtoul(buf, NULL, 10) & 0xff;	fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]);	return count;}static ssize_t show_fan_pwm (struct fscher_data *data, char *buf, int nr){	return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]);}static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data,			   const char *buf, size_t count, int nr, int reg){	/* supported values: 2, 4, 8 */	unsigned long v = simple_strtoul(buf, NULL, 10);	switch (v) {	case 2: v = 1; break;	case 4: v = 2; break;	case 8: v = 3; break;	default:		dev_err(&client->dev, "fan_div value %ld not "			 "supported. Choose one of 2, 4 or 8!\n", v);		return -EINVAL;	}	/* bits 2..7 reserved => mask with 0x03 */	data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03;	data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v;	fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]);	return count;}static ssize_t show_fan_div(struct fscher_data *data, char *buf, int nr){	/* bits 2..7 reserved => mask with 0x03 */  	return sprintf(buf, "%u\n", 1 << (data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] & 0x03));}#define RPM_FROM_REG(val)	(val*60)static ssize_t show_fan_input (struct fscher_data *data, char *buf, int nr){	return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[FAN_INDEX_FROM_NUM(nr)]));}#define TEMP_INDEX_FROM_NUM(nr)		((nr) - 1)static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *data,			       const char *buf, size_t count, int nr, int reg){	/* bits 2..7 reserved, 0 read only => mask with 0x02 */  	unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;	data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v;	fscher_write_value(client, reg, v);	return count;}static ssize_t show_temp_status(struct fscher_data *data, char *buf, int nr){	/* bits 2..7 reserved => mask with 0x03 */	return sprintf(buf, "%u\n", data->temp_status[TEMP_INDEX_FROM_NUM(nr)] & 0x03);}#define TEMP_FROM_REG(val)	(((val) - 128) * 1000)static ssize_t show_temp_input(struct fscher_data *data, char *buf, int nr){	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[TEMP_INDEX_FROM_NUM(nr)]));}/* * The final conversion is specified in sensors.conf, as it depends on * mainboard specific values. We export the registers contents as * pseudo-hundredths-of-Volts (range 0V - 2.55V). Not that it makes much * sense per se, but it minimizes the conversions count and keeps the * values within a usual range. */#define VOLT_FROM_REG(val)	((val) * 10)static ssize_t show_in_input(struct fscher_data *data, char *buf, int nr){	return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[nr]));}static ssize_t show_revision(struct fscher_data *data, char *buf, int nr){	return sprintf(buf, "%u\n", data->revision);}static ssize_t show_alarms(struct fscher_data *data, char *buf, int nr){	/* bits 2, 5..6 reserved => mask with 0x9b */	return sprintf(buf, "%u\n", data->global_event & 0x9b);}static ssize_t set_control(struct i2c_client *client, struct fscher_data *data,			   const char *buf, size_t count, int nr, int reg){	/* bits 1..7 reserved => mask with 0x01 */  	unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01;	data->global_control &= ~v;	fscher_write_value(client, reg, v);	return count;}static ssize_t show_control(struct fscher_data *data, char *buf, int nr){	/* bits 1..7 reserved => mask with 0x01 */	return sprintf(buf, "%u\n", data->global_control & 0x01);}static ssize_t set_watchdog_control(struct i2c_client *client, struct				    fscher_data *data, const char *buf, size_t count,				    int nr, int reg){	/* bits 0..3 reserved => mask with 0xf0 */  	unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;	data->watchdog[2] &= ~0xf0;	data->watchdog[2] |= v;	fscher_write_value(client, reg, data->watchdog[2]);	return count;}static ssize_t show_watchdog_control(struct fscher_data *data, char *buf, int nr){	/* bits 0..3 reserved, bit 5 write only => mask with 0xd0 */	return sprintf(buf, "%u\n", data->watchdog[2] & 0xd0);}static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data *data,				   const char *buf, size_t count, int nr, int reg){	/* bits 0, 2..7 reserved => mask with 0x02 */  	unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;	data->watchdog[1] &= ~v;	fscher_write_value(client, reg, v);	return count;}static ssize_t show_watchdog_status(struct fscher_data *data, char *buf, int nr){	/* bits 0, 2..7 reserved => mask with 0x02 */	return sprintf(buf, "%u\n", data->watchdog[1] & 0x02);}static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data *data,				   const char *buf, size_t count, int nr, int reg){	data->watchdog[0] = simple_strtoul(buf, NULL, 10) & 0xff;	fscher_write_value(client, reg, data->watchdog[0]);	return count;}static ssize_t show_watchdog_preset(struct fscher_data *data, char *buf, int nr){	return sprintf(buf, "%u\n", data->watchdog[0]);}static int __init sensors_fscher_init(void){	return i2c_add_driver(&fscher_driver);}static void __exit sensors_fscher_exit(void){	i2c_del_driver(&fscher_driver);}MODULE_AUTHOR("Reinhard Nissl <rnissl@gmx.de>");MODULE_DESCRIPTION("FSC Hermes driver");MODULE_LICENSE("GPL");module_init(sensors_fscher_init);module_exit(sensors_fscher_exit);

⌨️ 快捷键说明

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