Skip to content

Commit 93e87d7

Browse files
mranostayjic23
authored andcommitted
iio: chemical: vz89x: rework i2c transfer reading
Add an optimized i2c transfer reading function, and fallback to racey smbus transfers if client->adapter doesn't support this. Signed-off-by: Matt Ranostay <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 4c3e2a4 commit 93e87d7

File tree

1 file changed

+52
-14
lines changed

1 file changed

+52
-14
lines changed

drivers/iio/chemical/vz89x.c

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@
3434
struct vz89x_data {
3535
struct i2c_client *client;
3636
struct mutex lock;
37-
unsigned long last_update;
37+
int (*xfer)(struct vz89x_data *data, u8 cmd);
3838

39+
unsigned long last_update;
3940
u8 buffer[VZ89X_REG_MEASUREMENT_SIZE];
4041
};
4142

@@ -100,27 +101,60 @@ static int vz89x_measurement_is_valid(struct vz89x_data *data)
100101
return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0);
101102
}
102103

103-
static int vz89x_get_measurement(struct vz89x_data *data)
104+
static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd)
104105
{
106+
struct i2c_client *client = data->client;
107+
struct i2c_msg msg[2];
105108
int ret;
106-
int i;
109+
u8 buf[3] = { cmd, 0, 0};
107110

108-
/* sensor can only be polled once a second max per datasheet */
109-
if (!time_after(jiffies, data->last_update + HZ))
110-
return 0;
111+
msg[0].addr = client->addr;
112+
msg[0].flags = client->flags;
113+
msg[0].len = 3;
114+
msg[0].buf = (char *) &buf;
115+
116+
msg[1].addr = client->addr;
117+
msg[1].flags = client->flags | I2C_M_RD;
118+
msg[1].len = VZ89X_REG_MEASUREMENT_SIZE;
119+
msg[1].buf = (char *) &data->buffer;
120+
121+
ret = i2c_transfer(client->adapter, msg, 2);
111122

112-
ret = i2c_smbus_write_word_data(data->client,
113-
VZ89X_REG_MEASUREMENT, 0);
123+
return (ret == 2) ? 0 : ret;
124+
}
125+
126+
static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd)
127+
{
128+
struct i2c_client *client = data->client;
129+
int ret;
130+
int i;
131+
132+
ret = i2c_smbus_write_word_data(client, cmd, 0);
114133
if (ret < 0)
115134
return ret;
116135

117136
for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) {
118-
ret = i2c_smbus_read_byte(data->client);
137+
ret = i2c_smbus_read_byte(client);
119138
if (ret < 0)
120139
return ret;
121140
data->buffer[i] = ret;
122141
}
123142

143+
return 0;
144+
}
145+
146+
static int vz89x_get_measurement(struct vz89x_data *data)
147+
{
148+
int ret;
149+
150+
/* sensor can only be polled once a second max per datasheet */
151+
if (!time_after(jiffies, data->last_update + HZ))
152+
return 0;
153+
154+
ret = data->xfer(data, VZ89X_REG_MEASUREMENT);
155+
if (ret < 0)
156+
return ret;
157+
124158
ret = vz89x_measurement_is_valid(data);
125159
if (ret)
126160
return -EAGAIN;
@@ -204,15 +238,19 @@ static int vz89x_probe(struct i2c_client *client,
204238
struct iio_dev *indio_dev;
205239
struct vz89x_data *data;
206240

207-
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA |
208-
I2C_FUNC_SMBUS_BYTE))
209-
return -ENODEV;
210-
211241
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
212242
if (!indio_dev)
213243
return -ENOMEM;
214-
215244
data = iio_priv(indio_dev);
245+
246+
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
247+
data->xfer = vz89x_i2c_xfer;
248+
else if (i2c_check_functionality(client->adapter,
249+
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE))
250+
data->xfer = vz89x_smbus_xfer;
251+
else
252+
return -ENOTSUPP;
253+
216254
i2c_set_clientdata(client, indio_dev);
217255
data->client = client;
218256
data->last_update = jiffies - HZ;

0 commit comments

Comments
 (0)