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