|
34 | 34 | struct vz89x_data {
|
35 | 35 | struct i2c_client *client;
|
36 | 36 | struct mutex lock;
|
37 |
| - unsigned long last_update; |
| 37 | + int (*xfer)(struct vz89x_data *data, u8 cmd); |
38 | 38 |
|
| 39 | + unsigned long last_update; |
39 | 40 | u8 buffer[VZ89X_REG_MEASUREMENT_SIZE];
|
40 | 41 | };
|
41 | 42 |
|
@@ -100,27 +101,60 @@ static int vz89x_measurement_is_valid(struct vz89x_data *data)
|
100 | 101 | return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0);
|
101 | 102 | }
|
102 | 103 |
|
103 |
| -static int vz89x_get_measurement(struct vz89x_data *data) |
| 104 | +static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd) |
104 | 105 | {
|
| 106 | + struct i2c_client *client = data->client; |
| 107 | + struct i2c_msg msg[2]; |
105 | 108 | int ret;
|
106 |
| - int i; |
| 109 | + u8 buf[3] = { cmd, 0, 0}; |
107 | 110 |
|
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); |
111 | 122 |
|
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); |
114 | 133 | if (ret < 0)
|
115 | 134 | return ret;
|
116 | 135 |
|
117 | 136 | for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) {
|
118 |
| - ret = i2c_smbus_read_byte(data->client); |
| 137 | + ret = i2c_smbus_read_byte(client); |
119 | 138 | if (ret < 0)
|
120 | 139 | return ret;
|
121 | 140 | data->buffer[i] = ret;
|
122 | 141 | }
|
123 | 142 |
|
| 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 | + |
124 | 158 | ret = vz89x_measurement_is_valid(data);
|
125 | 159 | if (ret)
|
126 | 160 | return -EAGAIN;
|
@@ -204,15 +238,19 @@ static int vz89x_probe(struct i2c_client *client,
|
204 | 238 | struct iio_dev *indio_dev;
|
205 | 239 | struct vz89x_data *data;
|
206 | 240 |
|
207 |
| - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA | |
208 |
| - I2C_FUNC_SMBUS_BYTE)) |
209 |
| - return -ENODEV; |
210 |
| - |
211 | 241 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
212 | 242 | if (!indio_dev)
|
213 | 243 | return -ENOMEM;
|
214 |
| - |
215 | 244 | 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 | + |
216 | 254 | i2c_set_clientdata(client, indio_dev);
|
217 | 255 | data->client = client;
|
218 | 256 | data->last_update = jiffies - HZ;
|
|
0 commit comments