ADM1031 Driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Here is the new version of the ADM1030/ADM1031 driver.

It does not support auto fan control yet.

I have modified the driver to be more inline with lm85 one. Hope that
version will satisfy Jean :)

Indentation is not yet compliant with linux coding rules... sorry.

Implementation of auto fan control comming next.

Alex.
 

/*
    adm1031.c - Part of lm_sensors, Linux kernel modules for hardware
             monitoring
    Based on lm75.c and lm85.c
    Support adm1030 / adm1031
    Copyright (c) 1998, 1999  Frodo Looijaard <frodol at dds.nl>
    Copyright (c) 2004 Alexandre d'Alton <alex at alexdalton.org>

    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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>


/* Many ADM1031 constants specified below */
#define ADM1031_CONF1_MEN               0x01 /* monitoring enable */
#define ADM1031_CONF1_AEN               0x80 /* Auto / SW Control */

#define ADM1031_CONF2_TIEN              0x04 /* TACH input Enable  */

#define ADM1031_REG_FAN_SPEED(nr)   	(0x08 + (nr))

#define ADM1031_REG_FAN_DIV(nr)		(0x20  + (nr))
#define ADM1031_REG_PWM(nr)		(0x22)
#define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))


#define ADM1031_REG_TEMP_MAX(nr)		(0x14  + 4*(nr))
#define ADM1031_REG_TEMP_MIN(nr)		(0x15  + 4*(nr))
#define ADM1031_REG_TEMP_CRIT(nr)		(0x16  + 4*(nr))

#define ADM1031_REG_TEMP(nr)		        (0xa + (nr))
#define ADM1031_REG_AUTO_TEMP(nr)		(0x24 + (nr))

#define ADM1031_REG_CONF(nr)		        (nr)


/* Addresses to scan */
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, I2C_CLIENT_END
};
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };

/* Insmod parameters */
SENSORS_INSMOD_2(adm1030, adm1031);

/* Each client has this additional data */
struct adm1031_data {
  struct semaphore	update_lock;
  int                   chip_type;
  char			valid;		/* !=0 if following fields are valid */
  unsigned int		last_updated;	/* In jiffies */
  unsigned int		conf;
  unsigned int		fan[2];
  unsigned int	       	fan_div[2];
  unsigned int	       	fan_min[2];
  unsigned int	       	pwm[2];
  unsigned int          temp[3];
  unsigned int          auto_temp[3];
  unsigned int          temp_min[3];
  unsigned int          temp_max[3];
  unsigned int          temp_crit[3];
};

static int 
adm1031_attach_adapter(struct i2c_adapter *adapter);
static int 
adm1031_detect(struct i2c_adapter *adapter, int address, int kind);
static void 
adm1031_init_client(struct i2c_client *client);
static int 
adm1031_detach_client(struct i2c_client *client);
static int 
adm1031_read_value(struct i2c_client *client, u8 reg);
static int 
adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int
value);
static struct adm1031_data *
adm1031_update_device(struct device *dev);


/* This is the driver that will be inserted */
static struct i2c_driver adm1031_driver = {
	.owner		= THIS_MODULE,
	.name		= "adm1031",
	.flags		= I2C_DF_NOTIFY,
	.attach_adapter	= adm1031_attach_adapter,
	.detach_client	= adm1031_detach_client,
};

static int adm1031_id = 0;

#define TEMP_TO_REG(val)   ((val) / 1000)
#define TEMP_FROM_REG(val) ((val) * 1000)

#define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) :
0)
#define FAN_TO_REG(reg, div) FAN_FROM_REG(reg, div)

#define FAN_DIV_TO_REG(val) val == 8 ? 0xc0 :  \
	    val == 4 ? 0x80 :                  \
	    val == 2 ? 0x40 :                  \
	    val == 1 ? 0x00 : 0x00
#define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6))

#define PWM_TO_REG(val) (val)
#define PWM_FROM_REG(val) (val)

#define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) <<
2))
#define AUTO_TEMP_MAX_FROM_REG(reg) (5000 * (1<<((reg)&0x07))) +
(AUTO_TEMP_MIN_FROM_REG(reg))

#define AUTO_TEMP_MIN_TO_REG(val, reg) ((((val)/500) & 0xf8)|((reg) &
0x7))
static int AUTO_TEMP_MAX_TO_REG(int val, int reg)
{
  int ret;
  int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
  ret =  (((reg) & 0xf8) | \
	  (((range)<10000 ? 0 :                                   
	    (range)<20000 ? 1 :                                   
	    (range)<40000 ? 2 :                                   
	    (range)<80000 ? 3 : 4) & 7));
  return ret;
}

/* Fans */
static ssize_t show_fan(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 
						FAN_DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]) );
}
static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], 
						FAN_DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t set_fan_min(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;

	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	if (val)
	  data->fan_min[nr] = FAN_TO_REG(val,
FAN_DIV_FROM_REG(data->fan_div[nr]));
	else 
	  data->fan_min[nr] = 0xff;
	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
data->fan_min[nr]);
	up(&data->update_lock);
	return count;
}
static ssize_t set_fan_div(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;
	int     reg = adm1031_read_value(client, ADM1031_REG_FAN_DIV(nr));
 	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	data->fan_div[nr] = FAN_DIV_TO_REG(val);
	reg = (reg & 0x3f) | (data->fan_div[nr] & 0xc0);
	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
data->fan_div[nr]);
	up(&data->update_lock);
	return count;
}

#define show_fan_offset(offset)						\
static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
{									\
	return show_fan(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
{									\
	return show_fan_min(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)	\
{									\
	return show_fan_div(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t set_fan_##offset##_min (struct device *dev, 		\
	const char *buf, size_t count) 					\
{									\
	return set_fan_min(dev, buf, count, 0x##offset - 1);		\
}									\
static ssize_t set_fan_##offset##_div (struct device *dev, 		\
	const char *buf, size_t count) 					\
{									\
	return set_fan_div(dev, buf, count, 0x##offset - 1);		\
}									\
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset,
NULL) \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, 		\
		show_fan_##offset##_min, set_fan_##offset##_min)        \
static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, 		\
		show_fan_##offset##_div, set_fan_##offset##_div)

show_fan_offset(1);
show_fan_offset(2);


/* pwm */

static ssize_t show_pwm(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", data->pwm[nr]);
}
static ssize_t set_pwm(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;
	int     reg;
	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	data->pwm[nr] = PWM_TO_REG(val);
	reg = adm1031_read_value(client, ADM1031_REG_PWM(nr));
	adm1031_write_value(client, ADM1031_REG_PWM(nr), 
			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg&0xf) :
			    (data->pwm[nr] & 0xf) | (reg & 0xf0));
	up(&data->update_lock);
	return count;
}
#define show_pwm_reg(offset)						\
static ssize_t show_pwm_##offset (struct device *dev, char *buf)	\
{									\
	return show_pwm(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t set_pwm_##offset (struct device *dev,			\
				 const char *buf, size_t count)		\
{									\
	return set_pwm(dev, buf, count, 0x##offset - 1);		\
}									\
static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, 			\
		show_pwm_##offset, set_pwm_##offset)

show_pwm_reg(1);
show_pwm_reg(2);

/* Temps */
static ssize_t show_temp(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
}
static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]) );
}
static ssize_t set_temp_min(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;

	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	data->temp_min[nr] = TEMP_TO_REG(val);
	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
data->temp_min[nr]);
	up(&data->update_lock);
	return count;
}
static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
}
static ssize_t show_temp_crit(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr]) );
}
static ssize_t set_temp_max(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;

	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	data->temp_max[nr] = TEMP_TO_REG(val);
	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
data->temp_max[nr]);
	up(&data->update_lock);
	return count;
}
static ssize_t set_temp_crit(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;

	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	data->temp_max[nr] = TEMP_TO_REG(val);
	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
data->temp_crit[nr]);
	up(&data->update_lock);
	return count;
}

#define show_temp_reg(offset)						\
static ssize_t show_temp_##offset (struct device *dev, char *buf)	\
{									\
	return show_temp(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t show_temp_##offset##_min (struct device *dev, char
*buf)	\
{									\
	return show_temp_min(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t show_temp_##offset##_max (struct device *dev, char
*buf)	\
{									\
	return show_temp_max(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t show_temp_##offset##_crit (struct device *dev, char
*buf)	\
{									\
	return show_temp_crit(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t set_temp_##offset##_min (struct device *dev, 		\
	const char *buf, size_t count) 					\
{									\
	return set_temp_min(dev, buf, count, 0x##offset - 1);		\
}									\
static ssize_t set_temp_##offset##_max (struct device *dev, 		\
	const char *buf, size_t count) 					\
{									\
	return set_temp_max(dev, buf, count, 0x##offset - 1);		\
}									\
static ssize_t set_temp_##offset##_crit (struct device *dev, 		\
	const char *buf, size_t count) 					\
{									\
	return set_temp_crit(dev, buf, count, 0x##offset - 1);		\
}									\
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset,
NULL)	\
static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, 		\
		show_temp_##offset##_min, set_temp_##offset##_min)	\
static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\
		show_temp_##offset##_max, set_temp_##offset##_max)      \
static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, 		\
		show_temp_##offset##_crit, set_temp_##offset##_crit)

show_temp_reg(1);
show_temp_reg(2);
show_temp_reg(3);


/* Auto Temps */
static ssize_t show_auto_temp_off(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])
- 5000 );
}
static ssize_t show_auto_temp_min(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n",AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
}
static ssize_t set_auto_temp_min(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;

	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
data->auto_temp[nr]);
	up(&data->update_lock);
	return count;
}
static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr)
{
	struct adm1031_data *data = adm1031_update_device(dev);
	return sprintf(buf,"%d\n", AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])
);
}
static ssize_t set_auto_temp_max(struct device *dev, const char *buf, 
		size_t count, int nr)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int	val;

	down(&data->update_lock);
	val = simple_strtol(buf, NULL, 10);
	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr]);
	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
data->temp_max[nr]);
	up(&data->update_lock);
	return count;
}
#define show_auto_temp_reg(offset)						\
static ssize_t show_auto_temp_##offset##_off (struct device *dev, char
*buf)	\
{									\
	return show_auto_temp_off(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t show_auto_temp_##offset##_min (struct device *dev, char
*buf)	\
{									\
	return show_auto_temp_min(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t show_auto_temp_##offset##_max (struct device *dev, char
*buf)	\
{									\
	return show_auto_temp_max(dev, buf, 0x##offset - 1);			\
}									\
static ssize_t set_auto_temp_##offset##_min (struct device *dev, 		\
	const char *buf, size_t count) 					\
{									\
	return set_auto_temp_min(dev, buf, count, 0x##offset - 1);		\
}									\
static ssize_t set_auto_temp_##offset##_max (struct device *dev, 		\
	const char *buf, size_t count) 					\
{									\
	return set_auto_temp_max(dev, buf, count, 0x##offset - 1);		\
}									\
static DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,
show_auto_temp_##offset##_off, NULL)	\
static DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR, 		\
		show_auto_temp_##offset##_min, set_auto_temp_##offset##_min)	\
static DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR, 		\
		show_auto_temp_##offset##_max, set_auto_temp_##offset##_max)      \

show_auto_temp_reg(1);
show_auto_temp_reg(2);
show_auto_temp_reg(3);


static int adm1031_attach_adapter(struct i2c_adapter *adapter)
{
	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
		return 0;
	return i2c_detect(adapter, &addr_data, adm1031_detect);
}

/* This function is called by i2c_detect */
static int adm1031_detect(struct i2c_adapter *adapter, int address, int
kind)
{
	struct i2c_client *new_client;
	struct adm1031_data *data;
	int err = 0;
	const char *name = "";

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
				     I2C_FUNC_SMBUS_WORD_DATA))
		goto exit;

	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
				   sizeof(struct adm1031_data),
				   GFP_KERNEL))) {
		err = -ENOMEM;
		goto exit;
	}
	memset(new_client, 0x00, sizeof(struct i2c_client) +
				 sizeof(struct adm1031_data));

	data = (struct adm1031_data *) (new_client + 1);
	i2c_set_clientdata(new_client, data);
	new_client->addr = address;
	new_client->adapter = adapter;
	new_client->driver = &adm1031_driver;
	new_client->flags = 0;

	if (kind < 0) {
	  int id, co;
	  id = i2c_smbus_read_byte_data(new_client, 0x3d);
	  co = i2c_smbus_read_byte_data(new_client, 0x3e);
	  
	  if(( (id != 0x31)||(id != 0x30)) && (co != 0x41))
	    goto exit_free;
	  kind = (id == 0x30) ? adm1030 : adm1031;
	}

	if (kind <= 0)
		kind = adm1031;

	if (kind == adm1030) {
		name = "adm1030";
	}
	if (kind == adm1031) {
		name = "adm1031";
	}
	data->chip_type = kind;

	strlcpy(new_client->name, name, I2C_NAME_SIZE);

	new_client->id = adm1031_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 exit_free;

	/* Initialize the ADM1031 chip */
	adm1031_init_client(new_client);
	
	/* Register sysfs hooks */
	device_create_file(&new_client->dev, &dev_attr_fan1_input);
	device_create_file(&new_client->dev, &dev_attr_fan1_div);
	device_create_file(&new_client->dev, &dev_attr_fan1_min);
	device_create_file(&new_client->dev, &dev_attr_fan1_pwm);
	device_create_file(&new_client->dev, &dev_attr_temp1_input);
	device_create_file(&new_client->dev, &dev_attr_temp1_min);
	device_create_file(&new_client->dev, &dev_attr_temp1_max);
	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
	device_create_file(&new_client->dev, &dev_attr_temp2_input);
	device_create_file(&new_client->dev, &dev_attr_temp2_min);
	device_create_file(&new_client->dev, &dev_attr_temp2_max);
	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
	
	device_create_file(&new_client->dev, &dev_attr_auto_temp1_off);
	device_create_file(&new_client->dev, &dev_attr_auto_temp1_min);
	device_create_file(&new_client->dev, &dev_attr_auto_temp1_max);
	
	device_create_file(&new_client->dev, &dev_attr_auto_temp2_off);
	device_create_file(&new_client->dev, &dev_attr_auto_temp2_min);
	device_create_file(&new_client->dev, &dev_attr_auto_temp2_max);
	
	if (kind == adm1031){
	  device_create_file(&new_client->dev, &dev_attr_fan2_input);
	  device_create_file(&new_client->dev, &dev_attr_fan2_div);
	  device_create_file(&new_client->dev, &dev_attr_fan2_min);
	  device_create_file(&new_client->dev, &dev_attr_fan2_pwm);
	  device_create_file(&new_client->dev, &dev_attr_temp3_input);
	  device_create_file(&new_client->dev, &dev_attr_temp3_min);
	  device_create_file(&new_client->dev, &dev_attr_temp3_max);
	  device_create_file(&new_client->dev, &dev_attr_temp3_crit);
	  device_create_file(&new_client->dev, &dev_attr_auto_temp3_off);
	  device_create_file(&new_client->dev, &dev_attr_auto_temp3_min);
	  device_create_file(&new_client->dev, &dev_attr_auto_temp3_max);
	}

	return 0;

exit_free:
	kfree(new_client);
exit:
	return err;
}

static int adm1031_detach_client(struct i2c_client *client)
{
  int ret;
  if ( (ret = i2c_detach_client(client)) != 0 ){
    return ret;
  }
  kfree(client);
  return 0;
}

static int adm1031_read_value(struct i2c_client *client, u8 reg)
{
  return i2c_smbus_read_byte_data(client, reg);
}

static int adm1031_write_value(struct i2c_client *client, u8 reg,
unsigned int value)
{
    return i2c_smbus_write_byte_data(client, reg, value);
}

static void adm1031_init_client(struct i2c_client *client)
{
    unsigned int read_val;

    /* Initialize the ADM1031 chip (enables fan speed reading )*/
    read_val = adm1031_read_value(client, ADM1031_REG_CONF(1));
    adm1031_write_value(client, ADM1031_REG_CONF(1), read_val |
			ADM1031_CONF2_TIEN);

}

static struct adm1031_data *adm1031_update_device(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct adm1031_data *data = i2c_get_clientdata(client);
	int chan;

	down(&data->update_lock);

	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
	    (jiffies < data->last_updated) || !data->valid) {
		dev_dbg(&client->dev, "Starting adm1031 update\n");
		
		for (chan = 0; chan < ((data->chip_type == adm1031) ? 3 : 2); chan++){
		  data->temp[chan] =
		    adm1031_read_value(client, 
				       ADM1031_REG_TEMP(chan));
		  data->temp_min[chan] = 
		    adm1031_read_value(client, 
				       ADM1031_REG_TEMP_MIN(chan));
		  data->temp_max[chan] = 
		    adm1031_read_value(client, 
				       ADM1031_REG_TEMP_MAX(chan));
		  data->temp_crit[chan] = 
		    adm1031_read_value(client, 
				       ADM1031_REG_TEMP_CRIT(chan));

		  data->auto_temp[chan] =
		    adm1031_read_value(client, 
				       ADM1031_REG_AUTO_TEMP(chan));
		}
		
		data->conf = 
		  adm1031_read_value(client,
				     ADM1031_REG_CONF(0)); 
		data->fan_div[0]   = 
		  adm1031_read_value(client,
				     ADM1031_REG_FAN_DIV(0)); 
		data->fan[0] =
		  adm1031_read_value(client,
				     ADM1031_REG_FAN_SPEED(0));
		data->pwm[0]       = 0xf &
		    adm1031_read_value(client, ADM1031_REG_PWM(0));
		data->last_updated = jiffies;
		data->valid = 1;
	}

	up(&data->update_lock);

	return data;
}

static int __init sensors_adm1031_init(void)
{
	return i2c_add_driver(&adm1031_driver);
}

static void __exit sensors_adm1031_exit(void)
{
	i2c_del_driver(&adm1031_driver);
}

MODULE_AUTHOR("Alexandre d'Alton <alex at alexdalton.org>");
MODULE_DESCRIPTION("ADM1031 driver");
MODULE_LICENSE("GPL");

module_init(sensors_adm1031_init);
module_exit(sensors_adm1031_exit);




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux