hwmon: (lm90) Rearrange code to no longer require forward declarations
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
Родитель
06e1c0a216
Коммит
15b66ab690
|
@ -163,21 +163,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
|
||||||
#define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */
|
#define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */
|
||||||
#define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */
|
#define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions declaration
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info);
|
|
||||||
static int lm90_probe(struct i2c_client *client,
|
|
||||||
const struct i2c_device_id *id);
|
|
||||||
static void lm90_init_client(struct i2c_client *client);
|
|
||||||
static void lm90_alert(struct i2c_client *client, unsigned int flag);
|
|
||||||
static int lm90_remove(struct i2c_client *client);
|
|
||||||
static struct lm90_data *lm90_update_device(struct device *dev);
|
|
||||||
static inline void lm90_select_remote_channel(struct i2c_client *client,
|
|
||||||
struct lm90_data *data,
|
|
||||||
int channel);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Driver data (common to all clients)
|
* Driver data (common to all clients)
|
||||||
*/
|
*/
|
||||||
|
@ -204,19 +189,6 @@ static const struct i2c_device_id lm90_id[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, lm90_id);
|
MODULE_DEVICE_TABLE(i2c, lm90_id);
|
||||||
|
|
||||||
static struct i2c_driver lm90_driver = {
|
|
||||||
.class = I2C_CLASS_HWMON,
|
|
||||||
.driver = {
|
|
||||||
.name = "lm90",
|
|
||||||
},
|
|
||||||
.probe = lm90_probe,
|
|
||||||
.remove = lm90_remove,
|
|
||||||
.alert = lm90_alert,
|
|
||||||
.id_table = lm90_id,
|
|
||||||
.detect = lm90_detect,
|
|
||||||
.address_list = normal_i2c,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Client data (each client gets its own)
|
* Client data (each client gets its own)
|
||||||
*/
|
*/
|
||||||
|
@ -255,6 +227,209 @@ struct lm90_data {
|
||||||
u16 alarms; /* bitvector (upper 8 bits for max6695/96) */
|
u16 alarms; /* bitvector (upper 8 bits for max6695/96) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The ADM1032 supports PEC but not on write byte transactions, so we need
|
||||||
|
* to explicitly ask for a transaction without PEC.
|
||||||
|
*/
|
||||||
|
static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
|
||||||
|
{
|
||||||
|
return i2c_smbus_xfer(client->adapter, client->addr,
|
||||||
|
client->flags & ~I2C_CLIENT_PEC,
|
||||||
|
I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is assumed that client->update_lock is held (unless we are in
|
||||||
|
* detection or initialization steps). This matters when PEC is enabled,
|
||||||
|
* because we don't want the address pointer to change between the write
|
||||||
|
* byte and the read byte transactions.
|
||||||
|
*/
|
||||||
|
static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (client->flags & I2C_CLIENT_PEC) {
|
||||||
|
err = adm1032_write_byte(client, reg);
|
||||||
|
if (err >= 0)
|
||||||
|
err = i2c_smbus_read_byte(client);
|
||||||
|
} else
|
||||||
|
err = i2c_smbus_read_byte_data(client, reg);
|
||||||
|
|
||||||
|
if (err < 0) {
|
||||||
|
dev_warn(&client->dev, "Register %#02x read failed (%d)\n",
|
||||||
|
reg, err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*value = err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
u8 oldh, newh, l;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is a trick here. We have to read two registers to have the
|
||||||
|
* sensor temperature, but we have to beware a conversion could occur
|
||||||
|
* inbetween the readings. The datasheet says we should either use
|
||||||
|
* the one-shot conversion register, which we don't want to do
|
||||||
|
* (disables hardware monitoring) or monitor the busy bit, which is
|
||||||
|
* impossible (we can't read the values and monitor that bit at the
|
||||||
|
* exact same time). So the solution used here is to read the high
|
||||||
|
* byte once, then the low byte, then the high byte again. If the new
|
||||||
|
* high byte matches the old one, then we have a valid reading. Else
|
||||||
|
* we have to read the low byte again, and now we believe we have a
|
||||||
|
* correct reading.
|
||||||
|
*/
|
||||||
|
if ((err = lm90_read_reg(client, regh, &oldh))
|
||||||
|
|| (err = lm90_read_reg(client, regl, &l))
|
||||||
|
|| (err = lm90_read_reg(client, regh, &newh)))
|
||||||
|
return err;
|
||||||
|
if (oldh != newh) {
|
||||||
|
err = lm90_read_reg(client, regl, &l);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*value = (newh << 8) | l;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* client->update_lock must be held when calling this function (unless we are
|
||||||
|
* in detection or initialization steps), and while a remote channel other
|
||||||
|
* than channel 0 is selected. Also, calling code must make sure to re-select
|
||||||
|
* external channel 0 before releasing the lock. This is necessary because
|
||||||
|
* various registers have different meanings as a result of selecting a
|
||||||
|
* non-default remote channel.
|
||||||
|
*/
|
||||||
|
static inline void lm90_select_remote_channel(struct i2c_client *client,
|
||||||
|
struct lm90_data *data,
|
||||||
|
int channel)
|
||||||
|
{
|
||||||
|
u8 config;
|
||||||
|
|
||||||
|
if (data->kind == max6696) {
|
||||||
|
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
|
||||||
|
config &= ~0x08;
|
||||||
|
if (channel)
|
||||||
|
config |= 0x08;
|
||||||
|
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
|
||||||
|
config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct lm90_data *lm90_update_device(struct device *dev)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm90_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (time_after(jiffies, data->last_updated + HZ / 2 + HZ / 10)
|
||||||
|
|| !data->valid) {
|
||||||
|
u8 h, l;
|
||||||
|
u8 alarms;
|
||||||
|
|
||||||
|
dev_dbg(&client->dev, "Updating lm90 data.\n");
|
||||||
|
lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]);
|
||||||
|
lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]);
|
||||||
|
lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]);
|
||||||
|
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
|
||||||
|
lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
|
||||||
|
|
||||||
|
if (data->flags & LM90_HAVE_LOCAL_EXT) {
|
||||||
|
lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
|
||||||
|
MAX6657_REG_R_LOCAL_TEMPL,
|
||||||
|
&data->temp11[4]);
|
||||||
|
} else {
|
||||||
|
if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP,
|
||||||
|
&h) == 0)
|
||||||
|
data->temp11[4] = h << 8;
|
||||||
|
}
|
||||||
|
lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
|
||||||
|
LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]);
|
||||||
|
|
||||||
|
if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
|
||||||
|
data->temp11[1] = h << 8;
|
||||||
|
if ((data->flags & LM90_HAVE_REM_LIMIT_EXT)
|
||||||
|
&& lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
|
||||||
|
&l) == 0)
|
||||||
|
data->temp11[1] |= l;
|
||||||
|
}
|
||||||
|
if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
|
||||||
|
data->temp11[2] = h << 8;
|
||||||
|
if ((data->flags & LM90_HAVE_REM_LIMIT_EXT)
|
||||||
|
&& lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
|
||||||
|
&l) == 0)
|
||||||
|
data->temp11[2] |= l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->flags & LM90_HAVE_OFFSET) {
|
||||||
|
if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
|
||||||
|
&h) == 0
|
||||||
|
&& lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
|
||||||
|
&l) == 0)
|
||||||
|
data->temp11[3] = (h << 8) | l;
|
||||||
|
}
|
||||||
|
if (data->flags & LM90_HAVE_EMERGENCY) {
|
||||||
|
lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG,
|
||||||
|
&data->temp8[4]);
|
||||||
|
lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
|
||||||
|
&data->temp8[5]);
|
||||||
|
}
|
||||||
|
lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
|
||||||
|
data->alarms = alarms; /* save as 16 bit value */
|
||||||
|
|
||||||
|
if (data->kind == max6696) {
|
||||||
|
lm90_select_remote_channel(client, data, 1);
|
||||||
|
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT,
|
||||||
|
&data->temp8[6]);
|
||||||
|
lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
|
||||||
|
&data->temp8[7]);
|
||||||
|
lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
|
||||||
|
LM90_REG_R_REMOTE_TEMPL, &data->temp11[5]);
|
||||||
|
if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h))
|
||||||
|
data->temp11[6] = h << 8;
|
||||||
|
if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h))
|
||||||
|
data->temp11[7] = h << 8;
|
||||||
|
lm90_select_remote_channel(client, data, 0);
|
||||||
|
|
||||||
|
if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2,
|
||||||
|
&alarms))
|
||||||
|
data->alarms |= alarms << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-enable ALERT# output if it was originally enabled and
|
||||||
|
* relevant alarms are all clear */
|
||||||
|
if ((data->config_orig & 0x80) == 0
|
||||||
|
&& (data->alarms & data->alert_alarms) == 0) {
|
||||||
|
u8 config;
|
||||||
|
|
||||||
|
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
|
||||||
|
if (config & 0x80) {
|
||||||
|
dev_dbg(&client->dev, "Re-enabling ALERT#\n");
|
||||||
|
i2c_smbus_write_byte_data(client,
|
||||||
|
LM90_REG_W_CONFIG1,
|
||||||
|
config & ~0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->last_updated = jiffies;
|
||||||
|
data->valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Conversions
|
* Conversions
|
||||||
* For local temperatures and limits, critical limits and the hysteresis
|
* For local temperatures and limits, critical limits and the hysteresis
|
||||||
|
@ -770,68 +945,6 @@ static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
|
||||||
* Real code
|
* Real code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* The ADM1032 supports PEC but not on write byte transactions, so we need
|
|
||||||
* to explicitly ask for a transaction without PEC.
|
|
||||||
*/
|
|
||||||
static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
|
|
||||||
{
|
|
||||||
return i2c_smbus_xfer(client->adapter, client->addr,
|
|
||||||
client->flags & ~I2C_CLIENT_PEC,
|
|
||||||
I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It is assumed that client->update_lock is held (unless we are in
|
|
||||||
* detection or initialization steps). This matters when PEC is enabled,
|
|
||||||
* because we don't want the address pointer to change between the write
|
|
||||||
* byte and the read byte transactions.
|
|
||||||
*/
|
|
||||||
static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (client->flags & I2C_CLIENT_PEC) {
|
|
||||||
err = adm1032_write_byte(client, reg);
|
|
||||||
if (err >= 0)
|
|
||||||
err = i2c_smbus_read_byte(client);
|
|
||||||
} else
|
|
||||||
err = i2c_smbus_read_byte_data(client, reg);
|
|
||||||
|
|
||||||
if (err < 0) {
|
|
||||||
dev_warn(&client->dev, "Register %#02x read failed (%d)\n",
|
|
||||||
reg, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
*value = err;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* client->update_lock must be held when calling this function (unless we are
|
|
||||||
* in detection or initialization steps), and while a remote channel other
|
|
||||||
* than channel 0 is selected. Also, calling code must make sure to re-select
|
|
||||||
* external channel 0 before releasing the lock. This is necessary because
|
|
||||||
* various registers have different meanings as a result of selecting a
|
|
||||||
* non-default remote channel.
|
|
||||||
*/
|
|
||||||
static inline void lm90_select_remote_channel(struct i2c_client *client,
|
|
||||||
struct lm90_data *data,
|
|
||||||
int channel)
|
|
||||||
{
|
|
||||||
u8 config;
|
|
||||||
|
|
||||||
if (data->kind == max6696) {
|
|
||||||
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
|
|
||||||
config &= ~0x08;
|
|
||||||
if (channel)
|
|
||||||
config |= 0x08;
|
|
||||||
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
|
|
||||||
config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 0 if detection is successful, -ENODEV otherwise */
|
/* Return 0 if detection is successful, -ENODEV otherwise */
|
||||||
static int lm90_detect(struct i2c_client *new_client,
|
static int lm90_detect(struct i2c_client *new_client,
|
||||||
struct i2c_board_info *info)
|
struct i2c_board_info *info)
|
||||||
|
@ -1023,6 +1136,47 @@ static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
|
||||||
sysfs_remove_group(&client->dev.kobj, &lm90_group);
|
sysfs_remove_group(&client->dev.kobj, &lm90_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lm90_init_client(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
u8 config;
|
||||||
|
struct lm90_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the conversions.
|
||||||
|
*/
|
||||||
|
i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
|
||||||
|
5); /* 2 Hz */
|
||||||
|
if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) {
|
||||||
|
dev_warn(&client->dev, "Initialization failed!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data->config_orig = config;
|
||||||
|
|
||||||
|
/* Check Temperature Range Select */
|
||||||
|
if (data->kind == adt7461) {
|
||||||
|
if (config & 0x04)
|
||||||
|
data->flags |= LM90_FLAG_ADT7461_EXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put MAX6680/MAX8881 into extended resolution (bit 0x10,
|
||||||
|
* 0.125 degree resolution) and range (0x08, extend range
|
||||||
|
* to -64 degree) mode for the remote temperature sensor.
|
||||||
|
*/
|
||||||
|
if (data->kind == max6680)
|
||||||
|
config |= 0x18;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select external channel 0 for max6695/96
|
||||||
|
*/
|
||||||
|
if (data->kind == max6696)
|
||||||
|
config &= ~0x08;
|
||||||
|
|
||||||
|
config &= 0xBF; /* run */
|
||||||
|
if (config != data->config_orig) /* Only write if changed */
|
||||||
|
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
|
||||||
|
}
|
||||||
|
|
||||||
static int lm90_probe(struct i2c_client *new_client,
|
static int lm90_probe(struct i2c_client *new_client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -1134,47 +1288,6 @@ exit:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lm90_init_client(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
u8 config;
|
|
||||||
struct lm90_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start the conversions.
|
|
||||||
*/
|
|
||||||
i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
|
|
||||||
5); /* 2 Hz */
|
|
||||||
if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) {
|
|
||||||
dev_warn(&client->dev, "Initialization failed!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data->config_orig = config;
|
|
||||||
|
|
||||||
/* Check Temperature Range Select */
|
|
||||||
if (data->kind == adt7461) {
|
|
||||||
if (config & 0x04)
|
|
||||||
data->flags |= LM90_FLAG_ADT7461_EXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Put MAX6680/MAX8881 into extended resolution (bit 0x10,
|
|
||||||
* 0.125 degree resolution) and range (0x08, extend range
|
|
||||||
* to -64 degree) mode for the remote temperature sensor.
|
|
||||||
*/
|
|
||||||
if (data->kind == max6680)
|
|
||||||
config |= 0x18;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Select external channel 0 for max6695/96
|
|
||||||
*/
|
|
||||||
if (data->kind == max6696)
|
|
||||||
config &= ~0x08;
|
|
||||||
|
|
||||||
config &= 0xBF; /* run */
|
|
||||||
if (config != data->config_orig) /* Only write if changed */
|
|
||||||
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lm90_remove(struct i2c_client *client)
|
static int lm90_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct lm90_data *data = i2c_get_clientdata(client);
|
struct lm90_data *data = i2c_get_clientdata(client);
|
||||||
|
@ -1230,142 +1343,18 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
|
static struct i2c_driver lm90_driver = {
|
||||||
{
|
.class = I2C_CLASS_HWMON,
|
||||||
int err;
|
.driver = {
|
||||||
u8 oldh, newh, l;
|
.name = "lm90",
|
||||||
|
},
|
||||||
/*
|
.probe = lm90_probe,
|
||||||
* There is a trick here. We have to read two registers to have the
|
.remove = lm90_remove,
|
||||||
* sensor temperature, but we have to beware a conversion could occur
|
.alert = lm90_alert,
|
||||||
* inbetween the readings. The datasheet says we should either use
|
.id_table = lm90_id,
|
||||||
* the one-shot conversion register, which we don't want to do
|
.detect = lm90_detect,
|
||||||
* (disables hardware monitoring) or monitor the busy bit, which is
|
.address_list = normal_i2c,
|
||||||
* impossible (we can't read the values and monitor that bit at the
|
};
|
||||||
* exact same time). So the solution used here is to read the high
|
|
||||||
* byte once, then the low byte, then the high byte again. If the new
|
|
||||||
* high byte matches the old one, then we have a valid reading. Else
|
|
||||||
* we have to read the low byte again, and now we believe we have a
|
|
||||||
* correct reading.
|
|
||||||
*/
|
|
||||||
if ((err = lm90_read_reg(client, regh, &oldh))
|
|
||||||
|| (err = lm90_read_reg(client, regl, &l))
|
|
||||||
|| (err = lm90_read_reg(client, regh, &newh)))
|
|
||||||
return err;
|
|
||||||
if (oldh != newh) {
|
|
||||||
err = lm90_read_reg(client, regl, &l);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
*value = (newh << 8) | l;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct lm90_data *lm90_update_device(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct lm90_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + HZ / 2 + HZ / 10)
|
|
||||||
|| !data->valid) {
|
|
||||||
u8 h, l;
|
|
||||||
u8 alarms;
|
|
||||||
|
|
||||||
dev_dbg(&client->dev, "Updating lm90 data.\n");
|
|
||||||
lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]);
|
|
||||||
lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]);
|
|
||||||
lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]);
|
|
||||||
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
|
|
||||||
lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
|
|
||||||
|
|
||||||
if (data->flags & LM90_HAVE_LOCAL_EXT) {
|
|
||||||
lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
|
|
||||||
MAX6657_REG_R_LOCAL_TEMPL,
|
|
||||||
&data->temp11[4]);
|
|
||||||
} else {
|
|
||||||
if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP,
|
|
||||||
&h) == 0)
|
|
||||||
data->temp11[4] = h << 8;
|
|
||||||
}
|
|
||||||
lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
|
|
||||||
LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]);
|
|
||||||
|
|
||||||
if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
|
|
||||||
data->temp11[1] = h << 8;
|
|
||||||
if ((data->flags & LM90_HAVE_REM_LIMIT_EXT)
|
|
||||||
&& lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
|
|
||||||
&l) == 0)
|
|
||||||
data->temp11[1] |= l;
|
|
||||||
}
|
|
||||||
if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
|
|
||||||
data->temp11[2] = h << 8;
|
|
||||||
if ((data->flags & LM90_HAVE_REM_LIMIT_EXT)
|
|
||||||
&& lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
|
|
||||||
&l) == 0)
|
|
||||||
data->temp11[2] |= l;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->flags & LM90_HAVE_OFFSET) {
|
|
||||||
if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
|
|
||||||
&h) == 0
|
|
||||||
&& lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
|
|
||||||
&l) == 0)
|
|
||||||
data->temp11[3] = (h << 8) | l;
|
|
||||||
}
|
|
||||||
if (data->flags & LM90_HAVE_EMERGENCY) {
|
|
||||||
lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG,
|
|
||||||
&data->temp8[4]);
|
|
||||||
lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
|
|
||||||
&data->temp8[5]);
|
|
||||||
}
|
|
||||||
lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
|
|
||||||
data->alarms = alarms; /* save as 16 bit value */
|
|
||||||
|
|
||||||
if (data->kind == max6696) {
|
|
||||||
lm90_select_remote_channel(client, data, 1);
|
|
||||||
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT,
|
|
||||||
&data->temp8[6]);
|
|
||||||
lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
|
|
||||||
&data->temp8[7]);
|
|
||||||
lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
|
|
||||||
LM90_REG_R_REMOTE_TEMPL, &data->temp11[5]);
|
|
||||||
if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h))
|
|
||||||
data->temp11[6] = h << 8;
|
|
||||||
if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h))
|
|
||||||
data->temp11[7] = h << 8;
|
|
||||||
lm90_select_remote_channel(client, data, 0);
|
|
||||||
|
|
||||||
if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2,
|
|
||||||
&alarms))
|
|
||||||
data->alarms |= alarms << 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Re-enable ALERT# output if it was originally enabled and
|
|
||||||
* relevant alarms are all clear */
|
|
||||||
if ((data->config_orig & 0x80) == 0
|
|
||||||
&& (data->alarms & data->alert_alarms) == 0) {
|
|
||||||
u8 config;
|
|
||||||
|
|
||||||
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
|
|
||||||
if (config & 0x80) {
|
|
||||||
dev_dbg(&client->dev, "Re-enabling ALERT#\n");
|
|
||||||
i2c_smbus_write_byte_data(client,
|
|
||||||
LM90_REG_W_CONFIG1,
|
|
||||||
config & ~0x80);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data->last_updated = jiffies;
|
|
||||||
data->valid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&data->update_lock);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init sensors_lm90_init(void)
|
static int __init sensors_lm90_init(void)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче