Commit cf6ffb12 authored by Alison Schofield's avatar Alison Schofield Committed by Greg Kroah-Hartman

iio: humidity: hdc100x: fix sensor data reads of temp and humidity

commit 0d9dcf85 upstream.

Replace the i2c_smbus_read_byte commmands used to retrieve the sensor
data with an i2c_master_recv command.

The smbus read byte method fails because the device does not expect a
stop condition after sending the first byte. When we issue the second
read, we are getting the first byte again. Net effect is that of the 14
bits used for the measurement, the 8 most significant bits are correct,
the lower 6 are not.

None of the smbus read protocols follow the pattern this device requires
(S Addr Rd [A] Data [A] Data NA P), hence the switch to an i2c receive
transaction.

Applicable from original introduction of this driver, but will require
backporting due to churn in the code.
Signed-off-by: default avatarAlison Schofield <amsfield22@gmail.com>
Cc: Daniel Baluta <daniel.baluta@gmail.com>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e6b1db62
...@@ -142,7 +142,7 @@ static int hdc100x_get_measurement(struct hdc100x_data *data, ...@@ -142,7 +142,7 @@ static int hdc100x_get_measurement(struct hdc100x_data *data,
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
int delay = data->adc_int_us[chan->address]; int delay = data->adc_int_us[chan->address];
int ret; int ret;
int val; __be16 val;
/* start measurement */ /* start measurement */
ret = i2c_smbus_write_byte(client, chan->address); ret = i2c_smbus_write_byte(client, chan->address);
...@@ -154,26 +154,13 @@ static int hdc100x_get_measurement(struct hdc100x_data *data, ...@@ -154,26 +154,13 @@ static int hdc100x_get_measurement(struct hdc100x_data *data,
/* wait for integration time to pass */ /* wait for integration time to pass */
usleep_range(delay, delay + 1000); usleep_range(delay, delay + 1000);
/* /* read measurement */
* i2c_smbus_read_word_data cannot() be used here due to the command ret = i2c_master_recv(data->client, (char *)&val, sizeof(val));
* value not being understood and causes NAKs preventing any reading
* from being accessed.
*/
ret = i2c_smbus_read_byte(client);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "cannot read high byte measurement"); dev_err(&client->dev, "cannot read sensor data\n");
return ret; return ret;
} }
val = ret << 8; return be16_to_cpu(val);
ret = i2c_smbus_read_byte(client);
if (ret < 0) {
dev_err(&client->dev, "cannot read low byte measurement");
return ret;
}
val |= ret;
return val;
} }
static int hdc100x_get_heater_status(struct hdc100x_data *data) static int hdc100x_get_heater_status(struct hdc100x_data *data)
...@@ -272,8 +259,8 @@ static int hdc100x_probe(struct i2c_client *client, ...@@ -272,8 +259,8 @@ static int hdc100x_probe(struct i2c_client *client,
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct hdc100x_data *data; struct hdc100x_data *data;
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE)) I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
return -EOPNOTSUPP; return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
......
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