]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/iio/pressure/hp206c.c
Merge branch 'for-linus-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / drivers / iio / pressure / hp206c.c
1 /*
2  * hp206c.c - HOPERF HP206C precision barometer and altimeter sensor
3  *
4  * Copyright (c) 2016, Intel Corporation.
5  *
6  * This file is subject to the terms and conditions of version 2 of
7  * the GNU General Public License.  See the file COPYING in the main
8  * directory of this archive for more details.
9  *
10  * (7-bit I2C slave address 0x76)
11  *
12  * Datasheet:
13  *  http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
14  */
15
16 #include <linux/module.h>
17 #include <linux/i2c.h>
18 #include <linux/iio/iio.h>
19 #include <linux/iio/sysfs.h>
20 #include <linux/delay.h>
21 #include <linux/util_macros.h>
22 #include <linux/acpi.h>
23
24 /* I2C commands: */
25 #define HP206C_CMD_SOFT_RST     0x06
26
27 #define HP206C_CMD_ADC_CVT      0x40
28
29 #define HP206C_CMD_ADC_CVT_OSR_4096     0x00
30 #define HP206C_CMD_ADC_CVT_OSR_2048     0x04
31 #define HP206C_CMD_ADC_CVT_OSR_1024     0x08
32 #define HP206C_CMD_ADC_CVT_OSR_512      0x0c
33 #define HP206C_CMD_ADC_CVT_OSR_256      0x10
34 #define HP206C_CMD_ADC_CVT_OSR_128      0x14
35
36 #define HP206C_CMD_ADC_CVT_CHNL_PT      0x00
37 #define HP206C_CMD_ADC_CVT_CHNL_T       0x02
38
39 #define HP206C_CMD_READ_P       0x30
40 #define HP206C_CMD_READ_T       0x32
41
42 #define HP206C_CMD_READ_REG     0x80
43 #define HP206C_CMD_WRITE_REG    0xc0
44
45 #define HP206C_REG_INT_EN       0x0b
46 #define HP206C_REG_INT_CFG      0x0c
47
48 #define HP206C_REG_INT_SRC      0x0d
49 #define HP206C_FLAG_DEV_RDY     0x40
50
51 #define HP206C_REG_PARA         0x0f
52 #define HP206C_FLAG_CMPS_EN     0x80
53
54 /* Maximum spin for DEV_RDY */
55 #define HP206C_MAX_DEV_RDY_WAIT_COUNT 20
56 #define HP206C_DEV_RDY_WAIT_US    20000
57
58 struct hp206c_data {
59         struct mutex mutex;
60         struct i2c_client *client;
61         int temp_osr_index;
62         int pres_osr_index;
63 };
64
65 struct hp206c_osr_setting {
66         u8 osr_mask;
67         unsigned int temp_conv_time_us;
68         unsigned int pres_conv_time_us;
69 };
70
71 /* Data from Table 5 in datasheet. */
72 static const struct hp206c_osr_setting hp206c_osr_settings[] = {
73         { HP206C_CMD_ADC_CVT_OSR_4096,  65600,  131100  },
74         { HP206C_CMD_ADC_CVT_OSR_2048,  32800,  65600   },
75         { HP206C_CMD_ADC_CVT_OSR_1024,  16400,  32800   },
76         { HP206C_CMD_ADC_CVT_OSR_512,   8200,   16400   },
77         { HP206C_CMD_ADC_CVT_OSR_256,   4100,   8200    },
78         { HP206C_CMD_ADC_CVT_OSR_128,   2100,   4100    },
79 };
80 static const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 };
81 static const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128";
82
83 static inline int hp206c_read_reg(struct i2c_client *client, u8 reg)
84 {
85         return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg);
86 }
87
88 static inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val)
89 {
90         return i2c_smbus_write_byte_data(client,
91                         HP206C_CMD_WRITE_REG | reg, val);
92 }
93
94 static int hp206c_read_20bit(struct i2c_client *client, u8 cmd)
95 {
96         int ret;
97         u8 values[3];
98
99         ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values);
100         if (ret < 0)
101                 return ret;
102         if (ret != 3)
103                 return -EIO;
104         return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]);
105 }
106
107 /* Spin for max 160ms until DEV_RDY is 1, or return error. */
108 static int hp206c_wait_dev_rdy(struct iio_dev *indio_dev)
109 {
110         int ret;
111         int count = 0;
112         struct hp206c_data *data = iio_priv(indio_dev);
113         struct i2c_client *client = data->client;
114
115         while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) {
116                 ret = hp206c_read_reg(client, HP206C_REG_INT_SRC);
117                 if (ret < 0) {
118                         dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret);
119                         return ret;
120                 }
121                 if (ret & HP206C_FLAG_DEV_RDY)
122                         return 0;
123                 usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2);
124         }
125         return -ETIMEDOUT;
126 }
127
128 static int hp206c_set_compensation(struct i2c_client *client, bool enabled)
129 {
130         int val;
131
132         val = hp206c_read_reg(client, HP206C_REG_PARA);
133         if (val < 0)
134                 return val;
135         if (enabled)
136                 val |= HP206C_FLAG_CMPS_EN;
137         else
138                 val &= ~HP206C_FLAG_CMPS_EN;
139
140         return hp206c_write_reg(client, HP206C_REG_PARA, val);
141 }
142
143 /* Do a soft reset */
144 static int hp206c_soft_reset(struct iio_dev *indio_dev)
145 {
146         int ret;
147         struct hp206c_data *data = iio_priv(indio_dev);
148         struct i2c_client *client = data->client;
149
150         ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST);
151         if (ret) {
152                 dev_err(&client->dev, "Failed to reset device: %d\n", ret);
153                 return ret;
154         }
155
156         usleep_range(400, 600);
157
158         ret = hp206c_wait_dev_rdy(indio_dev);
159         if (ret) {
160                 dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret);
161                 return ret;
162         }
163
164         ret = hp206c_set_compensation(client, true);
165         if (ret)
166                 dev_err(&client->dev, "Failed to enable compensation: %d\n", ret);
167         return ret;
168 }
169
170 static int hp206c_conv_and_read(struct iio_dev *indio_dev,
171                                 u8 conv_cmd, u8 read_cmd,
172                                 unsigned int sleep_us)
173 {
174         int ret;
175         struct hp206c_data *data = iio_priv(indio_dev);
176         struct i2c_client *client = data->client;
177
178         ret = hp206c_wait_dev_rdy(indio_dev);
179         if (ret < 0) {
180                 dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
181                 return ret;
182         }
183
184         ret = i2c_smbus_write_byte(client, conv_cmd);
185         if (ret < 0) {
186                 dev_err(&indio_dev->dev, "Failed convert: %d\n", ret);
187                 return ret;
188         }
189
190         usleep_range(sleep_us, sleep_us * 3 / 2);
191
192         ret = hp206c_wait_dev_rdy(indio_dev);
193         if (ret < 0) {
194                 dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
195                 return ret;
196         }
197
198         ret = hp206c_read_20bit(client, read_cmd);
199         if (ret < 0)
200                 dev_err(&indio_dev->dev, "Failed read: %d\n", ret);
201
202         return ret;
203 }
204
205 static int hp206c_read_raw(struct iio_dev *indio_dev,
206                            struct iio_chan_spec const *chan, int *val,
207                            int *val2, long mask)
208 {
209         int ret;
210         struct hp206c_data *data = iio_priv(indio_dev);
211         const struct hp206c_osr_setting *osr_setting;
212         u8 conv_cmd;
213
214         mutex_lock(&data->mutex);
215
216         switch (mask) {
217         case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
218                 switch (chan->type) {
219                 case IIO_TEMP:
220                         *val = hp206c_osr_rates[data->temp_osr_index];
221                         ret = IIO_VAL_INT;
222                         break;
223
224                 case IIO_PRESSURE:
225                         *val = hp206c_osr_rates[data->pres_osr_index];
226                         ret = IIO_VAL_INT;
227                         break;
228                 default:
229                         ret = -EINVAL;
230                 }
231                 break;
232
233         case IIO_CHAN_INFO_RAW:
234                 switch (chan->type) {
235                 case IIO_TEMP:
236                         osr_setting = &hp206c_osr_settings[data->temp_osr_index];
237                         conv_cmd = HP206C_CMD_ADC_CVT |
238                                         osr_setting->osr_mask |
239                                         HP206C_CMD_ADC_CVT_CHNL_T;
240                         ret = hp206c_conv_and_read(indio_dev,
241                                         conv_cmd,
242                                         HP206C_CMD_READ_T,
243                                         osr_setting->temp_conv_time_us);
244                         if (ret >= 0) {
245                                 /* 20 significant bits are provided.
246                                  * Extend sign over the rest.
247                                  */
248                                 *val = sign_extend32(ret, 19);
249                                 ret = IIO_VAL_INT;
250                         }
251                         break;
252
253                 case IIO_PRESSURE:
254                         osr_setting = &hp206c_osr_settings[data->pres_osr_index];
255                         conv_cmd = HP206C_CMD_ADC_CVT |
256                                         osr_setting->osr_mask |
257                                         HP206C_CMD_ADC_CVT_CHNL_PT;
258                         ret = hp206c_conv_and_read(indio_dev,
259                                         conv_cmd,
260                                         HP206C_CMD_READ_P,
261                                         osr_setting->pres_conv_time_us);
262                         if (ret >= 0) {
263                                 *val = ret;
264                                 ret = IIO_VAL_INT;
265                         }
266                         break;
267                 default:
268                         ret = -EINVAL;
269                 }
270                 break;
271
272         case IIO_CHAN_INFO_SCALE:
273                 switch (chan->type) {
274                 case IIO_TEMP:
275                         *val = 0;
276                         *val2 = 10000;
277                         ret = IIO_VAL_INT_PLUS_MICRO;
278                         break;
279
280                 case IIO_PRESSURE:
281                         *val = 0;
282                         *val2 = 1000;
283                         ret = IIO_VAL_INT_PLUS_MICRO;
284                         break;
285                 default:
286                         ret = -EINVAL;
287                 }
288                 break;
289
290         default:
291                 ret = -EINVAL;
292         }
293
294         mutex_unlock(&data->mutex);
295         return ret;
296 }
297
298 static int hp206c_write_raw(struct iio_dev *indio_dev,
299                             struct iio_chan_spec const *chan,
300                             int val, int val2, long mask)
301 {
302         int ret = 0;
303         struct hp206c_data *data = iio_priv(indio_dev);
304
305         if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
306                 return -EINVAL;
307         mutex_lock(&data->mutex);
308         switch (chan->type) {
309         case IIO_TEMP:
310                 data->temp_osr_index = find_closest_descending(val,
311                         hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
312                 break;
313         case IIO_PRESSURE:
314                 data->pres_osr_index = find_closest_descending(val,
315                         hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
316                 break;
317         default:
318                 ret = -EINVAL;
319         }
320         mutex_unlock(&data->mutex);
321         return ret;
322 }
323
324 static const struct iio_chan_spec hp206c_channels[] = {
325         {
326                 .type = IIO_TEMP,
327                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
328                                       BIT(IIO_CHAN_INFO_SCALE) |
329                                       BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
330         },
331         {
332                 .type = IIO_PRESSURE,
333                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
334                                       BIT(IIO_CHAN_INFO_SCALE) |
335                                       BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
336         }
337 };
338
339 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str);
340
341 static struct attribute *hp206c_attributes[] = {
342         &iio_const_attr_sampling_frequency_available.dev_attr.attr,
343         NULL,
344 };
345
346 static const struct attribute_group hp206c_attribute_group = {
347         .attrs = hp206c_attributes,
348 };
349
350 static const struct iio_info hp206c_info = {
351         .attrs = &hp206c_attribute_group,
352         .read_raw = hp206c_read_raw,
353         .write_raw = hp206c_write_raw,
354         .driver_module = THIS_MODULE,
355 };
356
357 static int hp206c_probe(struct i2c_client *client,
358                         const struct i2c_device_id *id)
359 {
360         struct iio_dev *indio_dev;
361         struct hp206c_data *data;
362         int ret;
363
364         if (!i2c_check_functionality(client->adapter,
365                                      I2C_FUNC_SMBUS_BYTE |
366                                      I2C_FUNC_SMBUS_BYTE_DATA |
367                                      I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
368                 dev_err(&client->dev, "Adapter does not support "
369                                 "all required i2c functionality\n");
370                 return -ENODEV;
371         }
372
373         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
374         if (!indio_dev)
375                 return -ENOMEM;
376
377         data = iio_priv(indio_dev);
378         data->client = client;
379         mutex_init(&data->mutex);
380
381         indio_dev->info = &hp206c_info;
382         indio_dev->name = id->name;
383         indio_dev->dev.parent = &client->dev;
384         indio_dev->modes = INDIO_DIRECT_MODE;
385         indio_dev->channels = hp206c_channels;
386         indio_dev->num_channels = ARRAY_SIZE(hp206c_channels);
387
388         i2c_set_clientdata(client, indio_dev);
389
390         /* Do a soft reset on probe */
391         ret = hp206c_soft_reset(indio_dev);
392         if (ret) {
393                 dev_err(&client->dev, "Failed to reset on startup: %d\n", ret);
394                 return -ENODEV;
395         }
396
397         return devm_iio_device_register(&client->dev, indio_dev);
398 }
399
400 static const struct i2c_device_id hp206c_id[] = {
401         {"hp206c"},
402         {}
403 };
404
405 #ifdef CONFIG_ACPI
406 static const struct acpi_device_id hp206c_acpi_match[] = {
407         {"HOP206C", 0},
408         { },
409 };
410 MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
411 #endif
412
413 static struct i2c_driver hp206c_driver = {
414         .probe = hp206c_probe,
415         .id_table = hp206c_id,
416         .driver = {
417                 .name = "hp206c",
418                 .acpi_match_table = ACPI_PTR(hp206c_acpi_match),
419         },
420 };
421
422 module_i2c_driver(hp206c_driver);
423
424 MODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor");
425 MODULE_AUTHOR("Leonard Crestez <leonard.crestez@intel.com>");
426 MODULE_LICENSE("GPL v2");