hwmon: (ad7418) Catch I2C errors

If there is an i2c failure, the ad7416 reports its temperature as 0C.
Return an error code so users can properly detect errors.

Signed-off-by: Brandon Maier <brandon.maier@rockwellcollins.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Brandon Maier 2019-02-07 15:50:36 -06:00 committed by Guenter Roeck
parent e9b95485c1
commit 45034e4827
1 changed files with 48 additions and 15 deletions

View File

@ -54,10 +54,11 @@ struct ad7418_data {
u16 in[4];
};
static struct ad7418_data *ad7418_update_device(struct device *dev)
static int ad7418_update_device(struct device *dev)
{
struct ad7418_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
s32 val;
mutex_lock(&data->lock);
@ -67,47 +68,74 @@ static struct ad7418_data *ad7418_update_device(struct device *dev)
int i, ch;
/* read config register and clear channel bits */
cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
val = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
if (val < 0)
goto abort;
cfg = val;
cfg &= 0x1F;
i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
cfg | AD7418_CH_TEMP);
if (val < 0)
goto abort;
udelay(30);
for (i = 0; i < 3; i++) {
data->temp[i] =
i2c_smbus_read_word_swapped(client,
AD7418_REG_TEMP[i]);
val = i2c_smbus_read_word_swapped(client,
AD7418_REG_TEMP[i]);
if (val < 0)
goto abort;
data->temp[i] = val;
}
for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
i2c_smbus_write_byte_data(client,
AD7418_REG_CONF,
val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
cfg | AD7418_REG_ADC_CH(ch));
if (val < 0)
goto abort;
udelay(15);
data->in[data->adc_max - 1 - i] =
i2c_smbus_read_word_swapped(client,
AD7418_REG_ADC);
val = i2c_smbus_read_word_swapped(client,
AD7418_REG_ADC);
if (val < 0)
goto abort;
data->in[data->adc_max - 1 - i] = val;
}
/* restore old configuration value */
i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg);
val = i2c_smbus_write_word_swapped(client, AD7418_REG_CONF,
cfg);
if (val < 0)
goto abort;
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->lock);
return 0;
return data;
abort:
data->valid = 0;
mutex_unlock(&data->lock);
return val;
}
static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct ad7418_data *data = ad7418_update_device(dev);
struct ad7418_data *data = dev_get_drvdata(dev);
int ret;
ret = ad7418_update_device(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n",
LM75_TEMP_FROM_REG(data->temp[attr->index]));
}
@ -116,7 +144,12 @@ static ssize_t adc_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct ad7418_data *data = ad7418_update_device(dev);
struct ad7418_data *data = dev_get_drvdata(dev);
int ret;
ret = ad7418_update_device(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n",
((data->in[attr->index] >> 6) * 2500 + 512) / 1024);