Commit 37ad04d7 authored by Guenter Roeck's avatar Guenter Roeck

hwmon: (lm90) Simplify read functions

Return both error code and register value as return code from
read functions, and always check for errors.

This reduces code size on x86_64 by more than 1k while at
the same time improving error resiliency.
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 6e5f62b9
...@@ -171,7 +171,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, ...@@ -171,7 +171,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
#define SA56004_REG_R_LOCAL_TEMPL 0x22 #define SA56004_REG_R_LOCAL_TEMPL 0x22
#define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */
#define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */
/* TMP451 registers */ /* TMP451 registers */
...@@ -410,7 +409,7 @@ static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value) ...@@ -410,7 +409,7 @@ static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
* because we don't want the address pointer to change between the write * because we don't want the address pointer to change between the write
* byte and the read byte transactions. * byte and the read byte transactions.
*/ */
static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value) static int lm90_read_reg(struct i2c_client *client, u8 reg)
{ {
int err; int err;
...@@ -421,20 +420,12 @@ static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value) ...@@ -421,20 +420,12 @@ static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value)
} else } else
err = i2c_smbus_read_byte_data(client, reg); err = i2c_smbus_read_byte_data(client, reg);
if (err < 0) { return err;
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) static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl)
{ {
int err; int oldh, newh, l;
u8 oldh, newh, l;
/* /*
* There is a trick here. We have to read two registers to have the * There is a trick here. We have to read two registers to have the
...@@ -449,18 +440,21 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) ...@@ -449,18 +440,21 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
* we have to read the low byte again, and now we believe we have a * we have to read the low byte again, and now we believe we have a
* correct reading. * correct reading.
*/ */
if ((err = lm90_read_reg(client, regh, &oldh)) oldh = lm90_read_reg(client, regh);
|| (err = lm90_read_reg(client, regl, &l)) if (oldh < 0)
|| (err = lm90_read_reg(client, regh, &newh))) return oldh;
return err; l = lm90_read_reg(client, regl);
if (l < 0)
return l;
newh = lm90_read_reg(client, regh);
if (newh < 0)
return newh;
if (oldh != newh) { if (oldh != newh) {
err = lm90_read_reg(client, regl, &l); l = lm90_read_reg(client, regl);
if (err) if (l < 0)
return err; return l;
} }
*value = (newh << 8) | l; return (newh << 8) | l;
return 0;
} }
/* /*
...@@ -471,20 +465,23 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) ...@@ -471,20 +465,23 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
* various registers have different meanings as a result of selecting a * various registers have different meanings as a result of selecting a
* non-default remote channel. * non-default remote channel.
*/ */
static inline void lm90_select_remote_channel(struct i2c_client *client, static inline int lm90_select_remote_channel(struct i2c_client *client,
struct lm90_data *data, struct lm90_data *data,
int channel) int channel)
{ {
u8 config; int config;
if (data->kind == max6696) { if (data->kind == max6696) {
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); config = lm90_read_reg(client, LM90_REG_R_CONFIG1);
if (config < 0)
return config;
config &= ~0x08; config &= ~0x08;
if (channel) if (channel)
config |= 0x08; config |= 0x08;
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
config); config);
} }
return 0;
} }
/* /*
...@@ -516,104 +513,153 @@ static struct lm90_data *lm90_update_device(struct device *dev) ...@@ -516,104 +513,153 @@ static struct lm90_data *lm90_update_device(struct device *dev)
struct lm90_data *data = dev_get_drvdata(dev); struct lm90_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
unsigned long next_update; unsigned long next_update;
int val = 0;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
next_update = data->last_updated + next_update = data->last_updated +
msecs_to_jiffies(data->update_interval); msecs_to_jiffies(data->update_interval);
if (time_after(jiffies, next_update) || !data->valid) { if (time_after(jiffies, next_update) || !data->valid) {
u8 h, l;
u8 alarms;
dev_dbg(&client->dev, "Updating lm90 data.\n"); dev_dbg(&client->dev, "Updating lm90 data.\n");
lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, val = lm90_read_reg(client, LM90_REG_R_LOCAL_LOW);
&data->temp8[LOCAL_LOW]); if (val < 0)
lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, goto error;
&data->temp8[LOCAL_HIGH]); data->temp8[LOCAL_LOW] = val;
lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT,
&data->temp8[LOCAL_CRIT]); val = lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH);
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, if (val < 0)
&data->temp8[REMOTE_CRIT]); goto error;
lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); data->temp8[LOCAL_HIGH] = val;
val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT);
if (val < 0)
goto error;
data->temp8[LOCAL_CRIT] = val;
val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT);
if (val < 0)
goto error;
data->temp8[REMOTE_CRIT] = val;
val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST);
if (val < 0)
goto error;
data->temp_hyst = val;
if (data->reg_local_ext) { if (data->reg_local_ext) {
lm90_read16(client, LM90_REG_R_LOCAL_TEMP, val = lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
data->reg_local_ext, data->reg_local_ext);
&data->temp11[LOCAL_TEMP]); if (val < 0)
goto error;
data->temp11[LOCAL_TEMP] = val;
} else { } else {
if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, val = lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP);
&h) == 0) if (val < 0)
data->temp11[LOCAL_TEMP] = h << 8; goto error;
data->temp11[LOCAL_TEMP] = val << 8;
} }
lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, val = lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
LM90_REG_R_REMOTE_TEMPL, LM90_REG_R_REMOTE_TEMPL);
&data->temp11[REMOTE_TEMP]); if (val < 0)
goto error;
if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) { data->temp11[REMOTE_TEMP] = val;
data->temp11[REMOTE_LOW] = h << 8;
if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH);
&& lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, if (val < 0)
&l) == 0) goto error;
data->temp11[REMOTE_LOW] |= l; data->temp11[REMOTE_LOW] = val << 8;
if (data->flags & LM90_HAVE_REM_LIMIT_EXT) {
val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL);
if (val < 0)
goto error;
data->temp11[REMOTE_LOW] |= val;
} }
if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) { val = lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH);
data->temp11[REMOTE_HIGH] = h << 8; if (val < 0)
if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) goto error;
&& lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, data->temp11[REMOTE_HIGH] = val << 8;
&l) == 0) if (data->flags & LM90_HAVE_REM_LIMIT_EXT) {
data->temp11[REMOTE_HIGH] |= l; val = lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL);
if (val < 0)
goto error;
data->temp11[REMOTE_HIGH] |= val;
} }
if (data->flags & LM90_HAVE_OFFSET) { if (data->flags & LM90_HAVE_OFFSET) {
if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH, val = lm90_read16(client, LM90_REG_R_REMOTE_OFFSH,
&h) == 0 LM90_REG_R_REMOTE_OFFSL);
&& lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, if (val < 0)
&l) == 0) goto error;
data->temp11[REMOTE_OFFSET] = (h << 8) | l; data->temp11[REMOTE_OFFSET] = val;
} }
if (data->flags & LM90_HAVE_EMERGENCY) { if (data->flags & LM90_HAVE_EMERGENCY) {
lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG, val = lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG);
&data->temp8[LOCAL_EMERG]); if (val < 0)
lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, goto error;
&data->temp8[REMOTE_EMERG]); data->temp8[LOCAL_EMERG] = val;
val = lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG);
if (val < 0)
goto error;
data->temp8[REMOTE_EMERG] = val;
} }
lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); val = lm90_read_reg(client, LM90_REG_R_STATUS);
data->alarms = alarms; /* save as 16 bit value */ if (val < 0)
goto error;
data->alarms = val; /* lower 8 bit of alarms */
if (data->kind == max6696) { if (data->kind == max6696) {
lm90_select_remote_channel(client, data, 1); val = lm90_select_remote_channel(client, data, 1);
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, if (val < 0)
&data->temp8[REMOTE2_CRIT]); goto error;
lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
&data->temp8[REMOTE2_EMERG]); val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT);
lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, if (val < 0)
LM90_REG_R_REMOTE_TEMPL, goto error;
&data->temp11[REMOTE2_TEMP]); data->temp8[REMOTE2_CRIT] = val;
if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h))
data->temp11[REMOTE2_LOW] = h << 8; val = lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG);
if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h)) if (val < 0)
data->temp11[REMOTE2_HIGH] = h << 8; goto error;
data->temp8[REMOTE2_EMERG] = val;
val = lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
LM90_REG_R_REMOTE_TEMPL);
if (val < 0)
goto error;
data->temp11[REMOTE2_TEMP] = val;
val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH);
if (val < 0)
goto error;
data->temp11[REMOTE2_LOW] = val << 8;
val = lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH);
if (val < 0)
goto error;
data->temp11[REMOTE2_HIGH] = val << 8;
lm90_select_remote_channel(client, data, 0); lm90_select_remote_channel(client, data, 0);
if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2, val = lm90_read_reg(client, MAX6696_REG_R_STATUS2);
&alarms)) if (val < 0)
data->alarms |= alarms << 8; goto error;
data->alarms |= val << 8;
} }
/* /*
* Re-enable ALERT# output if it was originally enabled and * Re-enable ALERT# output if it was originally enabled and
* relevant alarms are all clear * relevant alarms are all clear
*/ */
if ((data->config_orig & 0x80) == 0 if (!(data->config_orig & 0x80) &&
&& (data->alarms & data->alert_alarms) == 0) { !(data->alarms & data->alert_alarms)) {
u8 config; val = lm90_read_reg(client, LM90_REG_R_CONFIG1);
if (val < 0)
goto error;
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); if (val & 0x80) {
if (config & 0x80) {
dev_dbg(&client->dev, "Re-enabling ALERT#\n"); dev_dbg(&client->dev, "Re-enabling ALERT#\n");
i2c_smbus_write_byte_data(client, i2c_smbus_write_byte_data(client,
LM90_REG_W_CONFIG1, LM90_REG_W_CONFIG1,
config & ~0x80); val & ~0x80);
} }
} }
...@@ -621,8 +667,12 @@ static struct lm90_data *lm90_update_device(struct device *dev) ...@@ -621,8 +667,12 @@ static struct lm90_data *lm90_update_device(struct device *dev)
data->valid = 1; data->valid = 1;
} }
error:
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
if (val < 0)
return ERR_PTR(val);
return data; return data;
} }
...@@ -764,6 +814,9 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, ...@@ -764,6 +814,9 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
struct lm90_data *data = lm90_update_device(dev); struct lm90_data *data = lm90_update_device(dev);
int temp; int temp;
if (IS_ERR(data))
return PTR_ERR(data);
if (data->kind == adt7461 || data->kind == tmp451) if (data->kind == adt7461 || data->kind == tmp451)
temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
else if (data->kind == max6646) else if (data->kind == max6646)
...@@ -830,6 +883,9 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, ...@@ -830,6 +883,9 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
struct lm90_data *data = lm90_update_device(dev); struct lm90_data *data = lm90_update_device(dev);
int temp; int temp;
if (IS_ERR(data))
return PTR_ERR(data);
if (data->kind == adt7461 || data->kind == tmp451) if (data->kind == adt7461 || data->kind == tmp451)
temp = temp_from_u16_adt7461(data, data->temp11[attr->index]); temp = temp_from_u16_adt7461(data, data->temp11[attr->index]);
else if (data->kind == max6646) else if (data->kind == max6646)
...@@ -905,6 +961,9 @@ static ssize_t show_temphyst(struct device *dev, ...@@ -905,6 +961,9 @@ static ssize_t show_temphyst(struct device *dev,
struct lm90_data *data = lm90_update_device(dev); struct lm90_data *data = lm90_update_device(dev);
int temp; int temp;
if (IS_ERR(data))
return PTR_ERR(data);
if (data->kind == adt7461 || data->kind == tmp451) if (data->kind == adt7461 || data->kind == tmp451)
temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
else if (data->kind == max6646) else if (data->kind == max6646)
...@@ -951,6 +1010,10 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, ...@@ -951,6 +1010,10 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
char *buf) char *buf)
{ {
struct lm90_data *data = lm90_update_device(dev); struct lm90_data *data = lm90_update_device(dev);
if (IS_ERR(data))
return PTR_ERR(data);
return sprintf(buf, "%d\n", data->alarms); return sprintf(buf, "%d\n", data->alarms);
} }
...@@ -961,6 +1024,9 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute ...@@ -961,6 +1024,9 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute
struct lm90_data *data = lm90_update_device(dev); struct lm90_data *data = lm90_update_device(dev);
int bitnr = attr->index; int bitnr = attr->index;
if (IS_ERR(data))
return PTR_ERR(data);
return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
} }
...@@ -1414,24 +1480,22 @@ static void lm90_restore_conf(void *_data) ...@@ -1414,24 +1480,22 @@ static void lm90_restore_conf(void *_data)
data->config_orig); data->config_orig);
} }
static void lm90_init_client(struct i2c_client *client, struct lm90_data *data) static int lm90_init_client(struct i2c_client *client, struct lm90_data *data)
{ {
u8 config, convrate; int config, convrate;
if (lm90_read_reg(client, LM90_REG_R_CONVRATE, &convrate) < 0) { convrate = lm90_read_reg(client, LM90_REG_R_CONVRATE);
dev_warn(&client->dev, "Failed to read convrate register!\n"); if (convrate < 0)
convrate = LM90_DEF_CONVRATE_RVAL; return convrate;
}
data->convrate_orig = convrate; data->convrate_orig = convrate;
/* /*
* Start the conversions. * Start the conversions.
*/ */
lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */
if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) { config = lm90_read_reg(client, LM90_REG_R_CONFIG1);
dev_warn(&client->dev, "Initialization failed!\n"); if (config < 0)
return; return config;
}
data->config_orig = config; data->config_orig = config;
/* Check Temperature Range Select */ /* Check Temperature Range Select */
...@@ -1459,17 +1523,24 @@ static void lm90_init_client(struct i2c_client *client, struct lm90_data *data) ...@@ -1459,17 +1523,24 @@ static void lm90_init_client(struct i2c_client *client, struct lm90_data *data)
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
devm_add_action(&client->dev, lm90_restore_conf, data); devm_add_action(&client->dev, lm90_restore_conf, data);
return 0;
} }
static bool lm90_is_tripped(struct i2c_client *client, u16 *status) static bool lm90_is_tripped(struct i2c_client *client, u16 *status)
{ {
struct lm90_data *data = i2c_get_clientdata(client); struct lm90_data *data = i2c_get_clientdata(client);
u8 st, st2 = 0; int st, st2 = 0;
lm90_read_reg(client, LM90_REG_R_STATUS, &st); st = lm90_read_reg(client, LM90_REG_R_STATUS);
if (st < 0)
return false;
if (data->kind == max6696) if (data->kind == max6696) {
lm90_read_reg(client, MAX6696_REG_R_STATUS2, &st2); st2 = lm90_read_reg(client, MAX6696_REG_R_STATUS2);
if (st2 < 0)
return false;
}
*status = st | (st2 << 8); *status = st | (st2 << 8);
...@@ -1571,7 +1642,11 @@ static int lm90_probe(struct i2c_client *client, ...@@ -1571,7 +1642,11 @@ static int lm90_probe(struct i2c_client *client,
data->max_convrate = lm90_params[data->kind].max_convrate; data->max_convrate = lm90_params[data->kind].max_convrate;
/* Initialize the LM90 chip */ /* Initialize the LM90 chip */
lm90_init_client(client, data); err = lm90_init_client(client, data);
if (err < 0) {
dev_err(dev, "Failed to initialize device\n");
return err;
}
/* Register sysfs hooks */ /* Register sysfs hooks */
data->groups[groups++] = &lm90_group; data->groups[groups++] = &lm90_group;
...@@ -1627,13 +1702,16 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag) ...@@ -1627,13 +1702,16 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag)
*/ */
struct lm90_data *data = i2c_get_clientdata(client); struct lm90_data *data = i2c_get_clientdata(client);
if ((data->flags & LM90_HAVE_BROKEN_ALERT) if ((data->flags & LM90_HAVE_BROKEN_ALERT) &&
&& (alarms & data->alert_alarms)) { (alarms & data->alert_alarms)) {
u8 config; int config;
dev_dbg(&client->dev, "Disabling ALERT#\n"); dev_dbg(&client->dev, "Disabling ALERT#\n");
lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); config = lm90_read_reg(client, LM90_REG_R_CONFIG1);
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, if (config >= 0)
config | 0x80); i2c_smbus_write_byte_data(client,
LM90_REG_W_CONFIG1,
config | 0x80);
} }
} else { } else {
dev_info(&client->dev, "Everything OK\n"); dev_info(&client->dev, "Everything OK\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment