mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-18 02:46:06 +00:00
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:
parent
e9b95485c1
commit
45034e4827
@ -54,10 +54,11 @@ struct ad7418_data {
|
|||||||
u16 in[4];
|
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 ad7418_data *data = dev_get_drvdata(dev);
|
||||||
struct i2c_client *client = data->client;
|
struct i2c_client *client = data->client;
|
||||||
|
s32 val;
|
||||||
|
|
||||||
mutex_lock(&data->lock);
|
mutex_lock(&data->lock);
|
||||||
|
|
||||||
@ -67,47 +68,74 @@ static struct ad7418_data *ad7418_update_device(struct device *dev)
|
|||||||
int i, ch;
|
int i, ch;
|
||||||
|
|
||||||
/* read config register and clear channel bits */
|
/* 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;
|
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);
|
cfg | AD7418_CH_TEMP);
|
||||||
|
if (val < 0)
|
||||||
|
goto abort;
|
||||||
|
|
||||||
udelay(30);
|
udelay(30);
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
data->temp[i] =
|
val = i2c_smbus_read_word_swapped(client,
|
||||||
i2c_smbus_read_word_swapped(client,
|
AD7418_REG_TEMP[i]);
|
||||||
AD7418_REG_TEMP[i]);
|
if (val < 0)
|
||||||
|
goto abort;
|
||||||
|
|
||||||
|
data->temp[i] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
|
for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
|
||||||
i2c_smbus_write_byte_data(client,
|
val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
|
||||||
AD7418_REG_CONF,
|
|
||||||
cfg | AD7418_REG_ADC_CH(ch));
|
cfg | AD7418_REG_ADC_CH(ch));
|
||||||
|
if (val < 0)
|
||||||
|
goto abort;
|
||||||
|
|
||||||
udelay(15);
|
udelay(15);
|
||||||
data->in[data->adc_max - 1 - i] =
|
val = i2c_smbus_read_word_swapped(client,
|
||||||
i2c_smbus_read_word_swapped(client,
|
AD7418_REG_ADC);
|
||||||
AD7418_REG_ADC);
|
if (val < 0)
|
||||||
|
goto abort;
|
||||||
|
|
||||||
|
data->in[data->adc_max - 1 - i] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore old configuration value */
|
/* 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->last_updated = jiffies;
|
||||||
data->valid = 1;
|
data->valid = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&data->lock);
|
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,
|
static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
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",
|
return sprintf(buf, "%d\n",
|
||||||
LM75_TEMP_FROM_REG(data->temp[attr->index]));
|
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)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
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",
|
return sprintf(buf, "%d\n",
|
||||||
((data->in[attr->index] >> 6) * 2500 + 512) / 1024);
|
((data->in[attr->index] >> 6) * 2500 + 512) / 1024);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user