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

📄 adt7470.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * A hwmon driver for the Analog Devices ADT7470 * Copyright (C) 2007 IBM * * Author: Darrick J. Wong <djwong@us.ibm.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <linux/module.h>#include <linux/jiffies.h>#include <linux/i2c.h>#include <linux/hwmon.h>#include <linux/hwmon-sysfs.h>#include <linux/err.h>#include <linux/mutex.h>#include <linux/delay.h>#include <linux/log2.h>/* Addresses to scan */static unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };/* Insmod parameters */I2C_CLIENT_INSMOD_1(adt7470);/* ADT7470 registers */#define ADT7470_REG_BASE_ADDR			0x20#define ADT7470_REG_TEMP_BASE_ADDR		0x20#define ADT7470_REG_TEMP_MAX_ADDR		0x29#define ADT7470_REG_FAN_BASE_ADDR		0x2A#define ADT7470_REG_FAN_MAX_ADDR		0x31#define ADT7470_REG_PWM_BASE_ADDR		0x32#define ADT7470_REG_PWM_MAX_ADDR		0x35#define ADT7470_REG_PWM_MAX_BASE_ADDR		0x38#define ADT7470_REG_PWM_MAX_MAX_ADDR		0x3B#define ADT7470_REG_CFG				0x40#define		ADT7470_FSPD_MASK		0x04#define ADT7470_REG_ALARM1			0x41#define ADT7470_REG_ALARM2			0x42#define ADT7470_REG_TEMP_LIMITS_BASE_ADDR	0x44#define ADT7470_REG_TEMP_LIMITS_MAX_ADDR	0x57#define ADT7470_REG_FAN_MIN_BASE_ADDR		0x58#define ADT7470_REG_FAN_MIN_MAX_ADDR		0x5F#define ADT7470_REG_FAN_MAX_BASE_ADDR		0x60#define ADT7470_REG_FAN_MAX_MAX_ADDR		0x67#define ADT7470_REG_PWM_CFG_BASE_ADDR		0x68#define ADT7470_REG_PWM12_CFG			0x68#define		ADT7470_PWM2_AUTO_MASK		0x40#define		ADT7470_PWM1_AUTO_MASK		0x80#define ADT7470_REG_PWM34_CFG			0x69#define		ADT7470_PWM3_AUTO_MASK		0x40#define		ADT7470_PWM4_AUTO_MASK		0x80#define	ADT7470_REG_PWM_MIN_BASE_ADDR		0x6A#define ADT7470_REG_PWM_MIN_MAX_ADDR		0x6D#define ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR	0x6E#define ADT7470_REG_PWM_TEMP_MIN_MAX_ADDR	0x71#define ADT7470_REG_ACOUSTICS12			0x75#define ADT7470_REG_ACOUSTICS34			0x76#define ADT7470_REG_DEVICE			0x3D#define ADT7470_REG_VENDOR			0x3E#define ADT7470_REG_REVISION			0x3F#define ADT7470_REG_ALARM1_MASK			0x72#define ADT7470_REG_ALARM2_MASK			0x73#define ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR	0x7C#define ADT7470_REG_PWM_AUTO_TEMP_MAX_ADDR	0x7D#define ADT7470_REG_MAX_ADDR			0x81#define ADT7470_TEMP_COUNT	10#define ADT7470_TEMP_REG(x)	(ADT7470_REG_TEMP_BASE_ADDR + (x))#define ADT7470_TEMP_MIN_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + ((x) * 2))#define ADT7470_TEMP_MAX_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + \				((x) * 2) + 1)#define ADT7470_FAN_COUNT	4#define ADT7470_REG_FAN(x)	(ADT7470_REG_FAN_BASE_ADDR + ((x) * 2))#define ADT7470_REG_FAN_MIN(x)	(ADT7470_REG_FAN_MIN_BASE_ADDR + ((x) * 2))#define ADT7470_REG_FAN_MAX(x)	(ADT7470_REG_FAN_MAX_BASE_ADDR + ((x) * 2))#define ADT7470_PWM_COUNT	4#define ADT7470_REG_PWM(x)	(ADT7470_REG_PWM_BASE_ADDR + (x))#define ADT7470_REG_PWM_MAX(x)	(ADT7470_REG_PWM_MAX_BASE_ADDR + (x))#define ADT7470_REG_PWM_MIN(x)	(ADT7470_REG_PWM_MIN_BASE_ADDR + (x))#define ADT7470_REG_PWM_TMIN(x)	(ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR + (x))#define ADT7470_REG_PWM_CFG(x)	(ADT7470_REG_PWM_CFG_BASE_ADDR + ((x) / 2))#define ADT7470_REG_PWM_AUTO_TEMP(x)	(ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR + \					((x) / 2))#define ADT7470_VENDOR		0x41#define ADT7470_DEVICE		0x70/* datasheet only mentions a revision 2 */#define ADT7470_REVISION	0x02/* "all temps" according to hwmon sysfs interface spec */#define ADT7470_PWM_ALL_TEMPS	0x3FF/* How often do we reread sensors values? (In jiffies) */#define SENSOR_REFRESH_INTERVAL	(5 * HZ)/* How often do we reread sensor limit values? (In jiffies) */#define LIMIT_REFRESH_INTERVAL	(60 * HZ)/* sleep 1s while gathering temperature data */#define TEMP_COLLECTION_TIME	1000#define power_of_2(x)	(((x) & ((x) - 1)) == 0)/* datasheet says to divide this number by the fan reading to get fan rpm */#define FAN_PERIOD_TO_RPM(x)	((90000 * 60) / (x))#define FAN_RPM_TO_PERIOD	FAN_PERIOD_TO_RPM#define FAN_PERIOD_INVALID	65535#define FAN_DATA_VALID(x)	((x) && (x) != FAN_PERIOD_INVALID)struct adt7470_data {	struct i2c_client	client;	struct device		*hwmon_dev;	struct attribute_group	attrs;	struct mutex		lock;	char			sensors_valid;	char			limits_valid;	unsigned long		sensors_last_updated;	/* In jiffies */	unsigned long		limits_last_updated;	/* In jiffies */	s8			temp[ADT7470_TEMP_COUNT];	s8			temp_min[ADT7470_TEMP_COUNT];	s8			temp_max[ADT7470_TEMP_COUNT];	u16			fan[ADT7470_FAN_COUNT];	u16			fan_min[ADT7470_FAN_COUNT];	u16			fan_max[ADT7470_FAN_COUNT];	u16			alarms, alarms_mask;	u8			force_pwm_max;	u8			pwm[ADT7470_PWM_COUNT];	u8			pwm_max[ADT7470_PWM_COUNT];	u8			pwm_automatic[ADT7470_PWM_COUNT];	u8			pwm_min[ADT7470_PWM_COUNT];	s8			pwm_tmin[ADT7470_PWM_COUNT];	u8			pwm_auto_temp[ADT7470_PWM_COUNT];};static int adt7470_attach_adapter(struct i2c_adapter *adapter);static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind);static int adt7470_detach_client(struct i2c_client *client);static struct i2c_driver adt7470_driver = {	.driver = {		.name	= "adt7470",	},	.attach_adapter	= adt7470_attach_adapter,	.detach_client	= adt7470_detach_client,};/* * 16-bit registers on the ADT7470 are low-byte first.  The data sheet says * that the low byte must be read before the high byte. */static inline int adt7470_read_word_data(struct i2c_client *client, u8 reg){	u16 foo;	foo = i2c_smbus_read_byte_data(client, reg);	foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8);	return foo;}static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg,					  u16 value){	return i2c_smbus_write_byte_data(client, reg, value & 0xFF)	       && i2c_smbus_write_byte_data(client, reg + 1, value >> 8);}static void adt7470_init_client(struct i2c_client *client){	int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);	if (reg < 0) {		dev_err(&client->dev, "cannot read configuration register\n");	} else {		/* start monitoring (and do a self-test) */		i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3);	}}static struct adt7470_data *adt7470_update_device(struct device *dev){	struct i2c_client *client = to_i2c_client(dev);	struct adt7470_data *data = i2c_get_clientdata(client);	unsigned long local_jiffies = jiffies;	u8 cfg;	int i;	mutex_lock(&data->lock);	if (time_before(local_jiffies, data->sensors_last_updated +		SENSOR_REFRESH_INTERVAL)		&& data->sensors_valid)		goto no_sensor_update;	/* start reading temperature sensors */	cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);	cfg |= 0x80;	i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);	/*	 * Delay is 200ms * number of tmp05 sensors.  Too bad	 * there's no way to figure out how many are connected.	 * For now, assume 1s will work.	 */	msleep(TEMP_COLLECTION_TIME);	/* done reading temperature sensors */	cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);	cfg &= ~0x80;	i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);	for (i = 0; i < ADT7470_TEMP_COUNT; i++)		data->temp[i] = i2c_smbus_read_byte_data(client,						ADT7470_TEMP_REG(i));	for (i = 0; i < ADT7470_FAN_COUNT; i++)		data->fan[i] = adt7470_read_word_data(client,						ADT7470_REG_FAN(i));	for (i = 0; i < ADT7470_PWM_COUNT; i++) {		int reg;		int reg_mask;		data->pwm[i] = i2c_smbus_read_byte_data(client,						ADT7470_REG_PWM(i));		if (i % 2)			reg_mask = ADT7470_PWM2_AUTO_MASK;		else			reg_mask = ADT7470_PWM1_AUTO_MASK;		reg = ADT7470_REG_PWM_CFG(i);		if (i2c_smbus_read_byte_data(client, reg) & reg_mask)			data->pwm_automatic[i] = 1;		else			data->pwm_automatic[i] = 0;		reg = ADT7470_REG_PWM_AUTO_TEMP(i);		cfg = i2c_smbus_read_byte_data(client, reg);		if (!(i % 2))			data->pwm_auto_temp[i] = cfg >> 4;		else			data->pwm_auto_temp[i] = cfg & 0xF;	}	if (i2c_smbus_read_byte_data(client, ADT7470_REG_CFG) &	    ADT7470_FSPD_MASK)		data->force_pwm_max = 1;	else		data->force_pwm_max = 0;	data->alarms = adt7470_read_word_data(client, ADT7470_REG_ALARM1);	data->alarms_mask = adt7470_read_word_data(client,						   ADT7470_REG_ALARM1_MASK);	data->sensors_last_updated = local_jiffies;	data->sensors_valid = 1;no_sensor_update:	if (time_before(local_jiffies, data->limits_last_updated +		LIMIT_REFRESH_INTERVAL)		&& data->limits_valid)		goto out;	for (i = 0; i < ADT7470_TEMP_COUNT; i++) {		data->temp_min[i] = i2c_smbus_read_byte_data(client,						ADT7470_TEMP_MIN_REG(i));		data->temp_max[i] = i2c_smbus_read_byte_data(client,						ADT7470_TEMP_MAX_REG(i));	}	for (i = 0; i < ADT7470_FAN_COUNT; i++) {		data->fan_min[i] = adt7470_read_word_data(client,						ADT7470_REG_FAN_MIN(i));		data->fan_max[i] = adt7470_read_word_data(client,						ADT7470_REG_FAN_MAX(i));	}	for (i = 0; i < ADT7470_PWM_COUNT; i++) {		data->pwm_max[i] = i2c_smbus_read_byte_data(client,						ADT7470_REG_PWM_MAX(i));		data->pwm_min[i] = i2c_smbus_read_byte_data(client,						ADT7470_REG_PWM_MIN(i));		data->pwm_tmin[i] = i2c_smbus_read_byte_data(client,						ADT7470_REG_PWM_TMIN(i));	}	data->limits_last_updated = local_jiffies;	data->limits_valid = 1;out:	mutex_unlock(&data->lock);	return data;}static ssize_t show_temp_min(struct device *dev,			     struct device_attribute *devattr,			     char *buf){	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);	struct adt7470_data *data = adt7470_update_device(dev);	return sprintf(buf, "%d\n", 1000 * data->temp_min[attr->index]);}static ssize_t set_temp_min(struct device *dev,			    struct device_attribute *devattr,			    const char *buf,			    size_t count){	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);	struct i2c_client *client = to_i2c_client(dev);	struct adt7470_data *data = i2c_get_clientdata(client);	int temp = simple_strtol(buf, NULL, 10) / 1000;	mutex_lock(&data->lock);	data->temp_min[attr->index] = temp;	i2c_smbus_write_byte_data(client, ADT7470_TEMP_MIN_REG(attr->index),				  temp);	mutex_unlock(&data->lock);	return count;}static ssize_t show_temp_max(struct device *dev,			     struct device_attribute *devattr,			     char *buf){	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);	struct adt7470_data *data = adt7470_update_device(dev);	return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]);}static ssize_t set_temp_max(struct device *dev,			    struct device_attribute *devattr,			    const char *buf,			    size_t count){	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);

⌨️ 快捷键说明

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