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

📄 lm80.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#define show_temp(suffix, value) \static ssize_t show_temp_##suffix(struct device *dev, char *buf) \{ \	struct lm80_data *data = lm80_update_device(dev); \	return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \}show_temp(hot_max, temp_hot_max);show_temp(hot_hyst, temp_hot_hyst);show_temp(os_max, temp_os_max);show_temp(os_hyst, temp_os_hyst);#define set_temp(suffix, value, reg) \static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \	size_t count) \{ \	struct i2c_client *client = to_i2c_client(dev); \	struct lm80_data *data = i2c_get_clientdata(client); \	long val = simple_strtoul(buf, NULL, 10); \	data->value = TEMP_LIMIT_TO_REG(val); \	lm80_write_value(client, reg, data->value); \	return count; \}set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX);set_temp(hot_hyst, temp_hot_hyst, LM80_REG_TEMP_HOT_HYST);set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX);set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);static ssize_t show_alarms(struct device *dev, char *buf){	struct lm80_data *data = lm80_update_device(dev);	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));}static DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min0, set_in_min0);static DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min1, set_in_min1);static DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min2, set_in_min2);static DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min3, set_in_min3);static DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min4, set_in_min4);static DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min5, set_in_min5);static DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min6, set_in_min6);static DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max0, set_in_max0);static DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max1, set_in_max1);static DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max2, set_in_max2);static DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max3, set_in_max3);static DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max4, set_in_max4);static DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max5, set_in_max5);static DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max6, set_in_max6);static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL);static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL);static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL);static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL);static DEVICE_ATTR(in4_input, S_IRUGO, show_in_input4, NULL);static DEVICE_ATTR(in5_input, S_IRUGO, show_in_input5, NULL);static DEVICE_ATTR(in6_input, S_IRUGO, show_in_input6, NULL);static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min1,    set_fan_min1);static DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min2,    set_fan_min2);static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL);static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL);static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div1, set_fan_div1);static DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div2, set_fan_div2);static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_hot_max,    set_temp_hot_max);static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hot_hyst,    set_temp_hot_hyst);static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_os_max,    set_temp_os_max);static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst,    set_temp_os_hyst);static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);/* * Real code */static int lm80_attach_adapter(struct i2c_adapter *adapter){	if (!(adapter->class & I2C_CLASS_HWMON))		return 0;	return i2c_detect(adapter, &addr_data, lm80_detect);}int lm80_detect(struct i2c_adapter *adapter, int address, int kind){	int i, cur;	struct i2c_client *new_client;	struct lm80_data *data;	int err = 0;	const char *name;	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))		goto exit;	/* OK. For now, we presume we have a valid client. We now create the	   client structure, even though we cannot fill it completely yet.	   But it allows us to access lm80_{read,write}_value. */	if (!(data = kmalloc(sizeof(struct lm80_data), GFP_KERNEL))) {		err = -ENOMEM;		goto exit;	}	memset(data, 0, sizeof(struct lm80_data));	new_client = &data->client;	i2c_set_clientdata(new_client, data);	new_client->addr = address;	new_client->adapter = adapter;	new_client->driver = &lm80_driver;	new_client->flags = 0;	/* Now, we do the remaining detection. It is lousy. */	if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0)		goto error_free;	for (i = 0x2a; i <= 0x3d; i++) {		cur = i2c_smbus_read_byte_data(new_client, i);		if ((i2c_smbus_read_byte_data(new_client, i + 0x40) != cur)		 || (i2c_smbus_read_byte_data(new_client, i + 0x80) != cur)		 || (i2c_smbus_read_byte_data(new_client, i + 0xc0) != cur))		    goto error_free;	}	/* Determine the chip type - only one kind supported! */	kind = lm80;	name = "lm80";	/* Fill in the remaining client fields and put it into the global list */	strlcpy(new_client->name, name, I2C_NAME_SIZE);	new_client->id = lm80_id++;	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 error_free;	/* Initialize the LM80 chip */	lm80_init_client(new_client);	/* A few vars need to be filled upon startup */	data->fan_min[0] = lm80_read_value(new_client, LM80_REG_FAN_MIN(1));	data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));	/* Register sysfs hooks */	device_create_file(&new_client->dev, &dev_attr_in0_min);	device_create_file(&new_client->dev, &dev_attr_in1_min);	device_create_file(&new_client->dev, &dev_attr_in2_min);	device_create_file(&new_client->dev, &dev_attr_in3_min);	device_create_file(&new_client->dev, &dev_attr_in4_min);	device_create_file(&new_client->dev, &dev_attr_in5_min);	device_create_file(&new_client->dev, &dev_attr_in6_min);	device_create_file(&new_client->dev, &dev_attr_in0_max);	device_create_file(&new_client->dev, &dev_attr_in1_max);	device_create_file(&new_client->dev, &dev_attr_in2_max);	device_create_file(&new_client->dev, &dev_attr_in3_max);	device_create_file(&new_client->dev, &dev_attr_in4_max);	device_create_file(&new_client->dev, &dev_attr_in5_max);	device_create_file(&new_client->dev, &dev_attr_in6_max);	device_create_file(&new_client->dev, &dev_attr_in0_input);	device_create_file(&new_client->dev, &dev_attr_in1_input);	device_create_file(&new_client->dev, &dev_attr_in2_input);	device_create_file(&new_client->dev, &dev_attr_in3_input);	device_create_file(&new_client->dev, &dev_attr_in4_input);	device_create_file(&new_client->dev, &dev_attr_in5_input);	device_create_file(&new_client->dev, &dev_attr_in6_input);	device_create_file(&new_client->dev, &dev_attr_fan1_min);	device_create_file(&new_client->dev, &dev_attr_fan2_min);	device_create_file(&new_client->dev, &dev_attr_fan1_input);	device_create_file(&new_client->dev, &dev_attr_fan2_input);	device_create_file(&new_client->dev, &dev_attr_fan1_div);	device_create_file(&new_client->dev, &dev_attr_fan2_div);	device_create_file(&new_client->dev, &dev_attr_temp1_input);	device_create_file(&new_client->dev, &dev_attr_temp1_max);	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);	device_create_file(&new_client->dev, &dev_attr_temp1_crit);	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);	device_create_file(&new_client->dev, &dev_attr_alarms);	return 0;error_free:	kfree(data);exit:	return err;}static int lm80_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 lm80_read_value(struct i2c_client *client, u8 reg){	return i2c_smbus_read_byte_data(client, reg);}static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value){	return i2c_smbus_write_byte_data(client, reg, value);}/* Called when we have found a new LM80. */static void lm80_init_client(struct i2c_client *client){	/* Reset all except Watchdog values and last conversion values	   This sets fan-divs to 2, among others. This makes most other	   initializations unnecessary */	lm80_write_value(client, LM80_REG_CONFIG, 0x80);	/* Set 11-bit temperature resolution */	lm80_write_value(client, LM80_REG_RES, 0x08);	/* Start monitoring */	lm80_write_value(client, LM80_REG_CONFIG, 0x01);}static struct lm80_data *lm80_update_device(struct device *dev){	struct i2c_client *client = to_i2c_client(dev);	struct lm80_data *data = i2c_get_clientdata(client);	int i;	down(&data->update_lock);	if ((jiffies - data->last_updated > 2 * HZ) ||	    (jiffies < data->last_updated) || !data->valid) {		dev_dbg(&client->dev, "Starting lm80 update\n");		for (i = 0; i <= 6; i++) {			data->in[i] =			    lm80_read_value(client, LM80_REG_IN(i));			data->in_min[i] =			    lm80_read_value(client, LM80_REG_IN_MIN(i));			data->in_max[i] =			    lm80_read_value(client, LM80_REG_IN_MAX(i));		}		data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);		data->fan_min[0] =		    lm80_read_value(client, LM80_REG_FAN_MIN(1));		data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);		data->fan_min[1] =		    lm80_read_value(client, LM80_REG_FAN_MIN(2));		data->temp =		    (lm80_read_value(client, LM80_REG_TEMP) << 8) |		    (lm80_read_value(client, LM80_REG_RES) & 0xf0);		data->temp_os_max =		    lm80_read_value(client, LM80_REG_TEMP_OS_MAX);		data->temp_os_hyst =		    lm80_read_value(client, LM80_REG_TEMP_OS_HYST);		data->temp_hot_max =		    lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);		data->temp_hot_hyst =		    lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);		i = lm80_read_value(client, LM80_REG_FANDIV);		data->fan_div[0] = (i >> 2) & 0x03;		data->fan_div[1] = (i >> 4) & 0x03;		data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +		    (lm80_read_value(client, LM80_REG_ALARM2) << 8);		data->last_updated = jiffies;		data->valid = 1;	}	up(&data->update_lock);	return data;}static int __init sensors_lm80_init(void){	return i2c_add_driver(&lm80_driver);}static void __exit sensors_lm80_exit(void){	i2c_del_driver(&lm80_driver);}MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "	"Philip Edelbrock <phil@netroedge.com>");MODULE_DESCRIPTION("LM80 driver");MODULE_LICENSE("GPL");module_init(sensors_lm80_init);module_exit(sensors_lm80_exit);

⌨️ 快捷键说明

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