Commit 45034e48 authored by Brandon Maier's avatar Brandon Maier Committed by Guenter Roeck
Browse files

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: default avatarBrandon Maier <brandon.maier@rockwellcollins.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent e9b95485
Loading
Loading
Loading
Loading
+48 −15
Original line number Diff line number Diff line
@@ -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,
			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,
			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);