iio:common: removed unused functions outside st_sensors library
[cascardo/linux.git] / drivers / iio / common / st_sensors / st_sensors_core.c
1 /*
2  * STMicroelectronics sensors core library driver
3  *
4  * Copyright 2012-2013 STMicroelectronics Inc.
5  *
6  * Denis Ciocca <denis.ciocca@st.com>
7  *
8  * Licensed under the GPL-2.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/delay.h>
15 #include <linux/iio/iio.h>
16 #include <asm/unaligned.h>
17
18 #include <linux/iio/common/st_sensors.h>
19
20
21 #define ST_SENSORS_WAI_ADDRESS          0x0f
22
23 static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
24                                                 u8 reg_addr, u8 mask, u8 data)
25 {
26         int err;
27         u8 new_data;
28         struct st_sensor_data *sdata = iio_priv(indio_dev);
29
30         err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data);
31         if (err < 0)
32                 goto st_sensors_write_data_with_mask_error;
33
34         new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask));
35         err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data);
36
37 st_sensors_write_data_with_mask_error:
38         return err;
39 }
40
41 static int st_sensors_match_odr(struct st_sensors *sensor,
42                         unsigned int odr, struct st_sensor_odr_avl *odr_out)
43 {
44         int i, ret = -EINVAL;
45
46         for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
47                 if (sensor->odr.odr_avl[i].hz == 0)
48                         goto st_sensors_match_odr_error;
49
50                 if (sensor->odr.odr_avl[i].hz == odr) {
51                         odr_out->hz = sensor->odr.odr_avl[i].hz;
52                         odr_out->value = sensor->odr.odr_avl[i].value;
53                         ret = 0;
54                         break;
55                 }
56         }
57
58 st_sensors_match_odr_error:
59         return ret;
60 }
61
62 int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
63 {
64         int err;
65         struct st_sensor_odr_avl odr_out;
66         struct st_sensor_data *sdata = iio_priv(indio_dev);
67
68         err = st_sensors_match_odr(sdata->sensor, odr, &odr_out);
69         if (err < 0)
70                 goto st_sensors_match_odr_error;
71
72         if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
73                         (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
74                 if (sdata->enabled == true) {
75                         err = st_sensors_write_data_with_mask(indio_dev,
76                                 sdata->sensor->odr.addr,
77                                 sdata->sensor->odr.mask,
78                                 odr_out.value);
79                 } else {
80                         err = 0;
81                 }
82         } else {
83                 err = st_sensors_write_data_with_mask(indio_dev,
84                         sdata->sensor->odr.addr, sdata->sensor->odr.mask,
85                         odr_out.value);
86         }
87         if (err >= 0)
88                 sdata->odr = odr_out.hz;
89
90 st_sensors_match_odr_error:
91         return err;
92 }
93 EXPORT_SYMBOL(st_sensors_set_odr);
94
95 static int st_sensors_match_fs(struct st_sensors *sensor,
96                                         unsigned int fs, int *index_fs_avl)
97 {
98         int i, ret = -EINVAL;
99
100         for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
101                 if (sensor->fs.fs_avl[i].num == 0)
102                         goto st_sensors_match_odr_error;
103
104                 if (sensor->fs.fs_avl[i].num == fs) {
105                         *index_fs_avl = i;
106                         ret = 0;
107                         break;
108                 }
109         }
110
111 st_sensors_match_odr_error:
112         return ret;
113 }
114
115 static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
116 {
117         int err, i;
118         struct st_sensor_data *sdata = iio_priv(indio_dev);
119
120         err = st_sensors_match_fs(sdata->sensor, fs, &i);
121         if (err < 0)
122                 goto st_accel_set_fullscale_error;
123
124         err = st_sensors_write_data_with_mask(indio_dev,
125                                 sdata->sensor->fs.addr,
126                                 sdata->sensor->fs.mask,
127                                 sdata->sensor->fs.fs_avl[i].value);
128         if (err < 0)
129                 goto st_accel_set_fullscale_error;
130
131         sdata->current_fullscale = (struct st_sensor_fullscale_avl *)
132                                                 &sdata->sensor->fs.fs_avl[i];
133         return err;
134
135 st_accel_set_fullscale_error:
136         dev_err(&indio_dev->dev, "failed to set new fullscale.\n");
137         return err;
138 }
139
140 int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable)
141 {
142         bool found;
143         u8 tmp_value;
144         int err = -EINVAL;
145         struct st_sensor_odr_avl odr_out;
146         struct st_sensor_data *sdata = iio_priv(indio_dev);
147
148         if (enable) {
149                 found = false;
150                 tmp_value = sdata->sensor->pw.value_on;
151                 if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
152                         (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
153                         err = st_sensors_match_odr(sdata->sensor,
154                                                         sdata->odr, &odr_out);
155                         if (err < 0)
156                                 goto set_enable_error;
157                         tmp_value = odr_out.value;
158                         found = true;
159                 }
160                 err = st_sensors_write_data_with_mask(indio_dev,
161                                 sdata->sensor->pw.addr,
162                                 sdata->sensor->pw.mask, tmp_value);
163                 if (err < 0)
164                         goto set_enable_error;
165
166                 sdata->enabled = true;
167
168                 if (found)
169                         sdata->odr = odr_out.hz;
170         } else {
171                 err = st_sensors_write_data_with_mask(indio_dev,
172                                 sdata->sensor->pw.addr,
173                                 sdata->sensor->pw.mask,
174                                 sdata->sensor->pw.value_off);
175                 if (err < 0)
176                         goto set_enable_error;
177
178                 sdata->enabled = false;
179         }
180
181 set_enable_error:
182         return err;
183 }
184 EXPORT_SYMBOL(st_sensors_set_enable);
185
186 int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
187 {
188         struct st_sensor_data *sdata = iio_priv(indio_dev);
189
190         return st_sensors_write_data_with_mask(indio_dev,
191                                 sdata->sensor->enable_axis.addr,
192                                 sdata->sensor->enable_axis.mask, axis_enable);
193 }
194 EXPORT_SYMBOL(st_sensors_set_axis_enable);
195
196 int st_sensors_init_sensor(struct iio_dev *indio_dev)
197 {
198         int err;
199         struct st_sensor_data *sdata = iio_priv(indio_dev);
200
201         mutex_init(&sdata->tb.buf_lock);
202
203         err = st_sensors_set_enable(indio_dev, false);
204         if (err < 0)
205                 goto init_error;
206
207         err = st_sensors_set_fullscale(indio_dev,
208                                                 sdata->current_fullscale->num);
209         if (err < 0)
210                 goto init_error;
211
212         err = st_sensors_set_odr(indio_dev, sdata->odr);
213         if (err < 0)
214                 goto init_error;
215
216         /* set BDU */
217         err = st_sensors_write_data_with_mask(indio_dev,
218                         sdata->sensor->bdu.addr, sdata->sensor->bdu.mask, true);
219         if (err < 0)
220                 goto init_error;
221
222         err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
223
224 init_error:
225         return err;
226 }
227 EXPORT_SYMBOL(st_sensors_init_sensor);
228
229 int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
230 {
231         int err;
232         struct st_sensor_data *sdata = iio_priv(indio_dev);
233
234         /* Enable/Disable the interrupt generator 1. */
235         if (sdata->sensor->drdy_irq.ig1.en_addr > 0) {
236                 err = st_sensors_write_data_with_mask(indio_dev,
237                         sdata->sensor->drdy_irq.ig1.en_addr,
238                         sdata->sensor->drdy_irq.ig1.en_mask, (int)enable);
239                 if (err < 0)
240                         goto st_accel_set_dataready_irq_error;
241         }
242
243         /* Enable/Disable the interrupt generator for data ready. */
244         err = st_sensors_write_data_with_mask(indio_dev,
245                         sdata->sensor->drdy_irq.addr,
246                         sdata->sensor->drdy_irq.mask, (int)enable);
247
248 st_accel_set_dataready_irq_error:
249         return err;
250 }
251 EXPORT_SYMBOL(st_sensors_set_dataready_irq);
252
253 int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale)
254 {
255         int err = -EINVAL, i;
256         struct st_sensor_data *sdata = iio_priv(indio_dev);
257
258         for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
259                 if ((sdata->sensor->fs.fs_avl[i].gain == scale) &&
260                                 (sdata->sensor->fs.fs_avl[i].gain != 0)) {
261                         err = 0;
262                         break;
263                 }
264         }
265         if (err < 0)
266                 goto st_sensors_match_scale_error;
267
268         err = st_sensors_set_fullscale(indio_dev,
269                                         sdata->sensor->fs.fs_avl[i].num);
270
271 st_sensors_match_scale_error:
272         return err;
273 }
274 EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain);
275
276 static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
277                                                         u8 ch_addr, int *data)
278 {
279         int err;
280         u8 outdata[ST_SENSORS_BYTE_FOR_CHANNEL];
281         struct st_sensor_data *sdata = iio_priv(indio_dev);
282
283         err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
284                                 ch_addr, ST_SENSORS_BYTE_FOR_CHANNEL,
285                                 outdata, sdata->multiread_bit);
286         if (err < 0)
287                 goto read_error;
288
289         *data = (s16)get_unaligned_le16(outdata);
290
291 read_error:
292         return err;
293 }
294
295 int st_sensors_read_info_raw(struct iio_dev *indio_dev,
296                                 struct iio_chan_spec const *ch, int *val)
297 {
298         int err;
299         struct st_sensor_data *sdata = iio_priv(indio_dev);
300
301         mutex_lock(&indio_dev->mlock);
302         if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
303                 err = -EBUSY;
304                 goto read_error;
305         } else {
306                 err = st_sensors_set_enable(indio_dev, true);
307                 if (err < 0)
308                         goto read_error;
309
310                 msleep((sdata->sensor->bootime * 1000) / sdata->odr);
311                 err = st_sensors_read_axis_data(indio_dev, ch->address, val);
312                 if (err < 0)
313                         goto read_error;
314
315                 *val = *val >> ch->scan_type.shift;
316         }
317         mutex_unlock(&indio_dev->mlock);
318
319         return err;
320
321 read_error:
322         mutex_unlock(&indio_dev->mlock);
323         return err;
324 }
325 EXPORT_SYMBOL(st_sensors_read_info_raw);
326
327 int st_sensors_check_device_support(struct iio_dev *indio_dev,
328                         int num_sensors_list, const struct st_sensors *sensors)
329 {
330         u8 wai;
331         int i, n, err;
332         struct st_sensor_data *sdata = iio_priv(indio_dev);
333
334         err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
335                                         ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai);
336         if (err < 0) {
337                 dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
338                 goto read_wai_error;
339         }
340
341         for (i = 0; i < num_sensors_list; i++) {
342                 if (sensors[i].wai == wai)
343                         break;
344         }
345         if (i == num_sensors_list)
346                 goto device_not_supported;
347
348         for (n = 0; n < ARRAY_SIZE(sensors[i].sensors_supported); n++) {
349                 if (strcmp(indio_dev->name,
350                                 &sensors[i].sensors_supported[n][0]) == 0)
351                         break;
352         }
353         if (n == ARRAY_SIZE(sensors[i].sensors_supported)) {
354                 dev_err(&indio_dev->dev, "device name and WhoAmI mismatch.\n");
355                 goto sensor_name_mismatch;
356         }
357
358         sdata->sensor = (struct st_sensors *)&sensors[i];
359
360         return i;
361
362 device_not_supported:
363         dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai);
364 sensor_name_mismatch:
365         err = -ENODEV;
366 read_wai_error:
367         return err;
368 }
369 EXPORT_SYMBOL(st_sensors_check_device_support);
370
371 ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
372                                 struct device_attribute *attr, char *buf)
373 {
374         struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev));
375
376         return sprintf(buf, "%d\n", adata->odr);
377 }
378 EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency);
379
380 ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
381                 struct device_attribute *attr, const char *buf, size_t size)
382 {
383         int err;
384         unsigned int odr;
385         struct iio_dev *indio_dev = dev_get_drvdata(dev);
386
387         err = kstrtoint(buf, 10, &odr);
388         if (err < 0)
389                 goto conversion_error;
390
391         mutex_lock(&indio_dev->mlock);
392         err = st_sensors_set_odr(indio_dev, odr);
393         mutex_unlock(&indio_dev->mlock);
394
395 conversion_error:
396         return err < 0 ? err : size;
397 }
398 EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency);
399
400 ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
401                                 struct device_attribute *attr, char *buf)
402 {
403         int i, len = 0;
404         struct iio_dev *indio_dev = dev_get_drvdata(dev);
405         struct st_sensor_data *sdata = iio_priv(indio_dev);
406
407         mutex_lock(&indio_dev->mlock);
408         for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
409                 if (sdata->sensor->odr.odr_avl[i].hz == 0)
410                         break;
411
412                 len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
413                                         sdata->sensor->odr.odr_avl[i].hz);
414         }
415         mutex_unlock(&indio_dev->mlock);
416         buf[len - 1] = '\n';
417
418         return len;
419 }
420 EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail);
421
422 ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
423                                 struct device_attribute *attr, char *buf)
424 {
425         int i, len = 0;
426         struct iio_dev *indio_dev = dev_get_drvdata(dev);
427         struct st_sensor_data *sdata = iio_priv(indio_dev);
428
429         mutex_lock(&indio_dev->mlock);
430         for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
431                 if (sdata->sensor->fs.fs_avl[i].num == 0)
432                         break;
433
434                 len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
435                                         sdata->sensor->fs.fs_avl[i].gain);
436         }
437         mutex_unlock(&indio_dev->mlock);
438         buf[len - 1] = '\n';
439
440         return len;
441 }
442 EXPORT_SYMBOL(st_sensors_sysfs_scale_avail);
443
444 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
445 MODULE_DESCRIPTION("STMicroelectronics ST-sensors core");
446 MODULE_LICENSE("GPL v2");