1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * STMicroelectronics gyroscopes driver
4 *
5 * Copyright 2012-2013 STMicroelectronics Inc.
6 *
7 * Denis Ciocca <denis.ciocca@st.com>
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/mutex.h>
13#include <linux/interrupt.h>
14#include <linux/sysfs.h>
15#include <linux/iio/iio.h>
16#include <linux/iio/sysfs.h>
17#include <linux/iio/trigger.h>
18
19#include <linux/iio/common/st_sensors.h>
20#include "st_gyro.h"
21
22#define ST_GYRO_NUMBER_DATA_CHANNELS 3
23
24/* DEFAULT VALUE FOR SENSORS */
25#define ST_GYRO_DEFAULT_OUT_X_L_ADDR 0x28
26#define ST_GYRO_DEFAULT_OUT_Y_L_ADDR 0x2a
27#define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c
28
29/* FULLSCALE */
30#define ST_GYRO_FS_AVL_245DPS 245
31#define ST_GYRO_FS_AVL_250DPS 250
32#define ST_GYRO_FS_AVL_500DPS 500
33#define ST_GYRO_FS_AVL_2000DPS 2000
34
35static const struct iio_mount_matrix *
36st_gyro_get_mount_matrix(const struct iio_dev *indio_dev,
37 const struct iio_chan_spec *chan)
38{
39 struct st_sensor_data *gdata = iio_priv(indio_dev);
40
41 return &gdata->mount_matrix;
42}
43
44static const struct iio_chan_spec_ext_info st_gyro_mount_matrix_ext_info[] = {
45 IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_gyro_get_mount_matrix),
46 { }
47};
48
49static const struct iio_chan_spec st_gyro_16bit_channels[] = {
50 ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
51 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
52 ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
53 ST_GYRO_DEFAULT_OUT_X_L_ADDR,
54 st_gyro_mount_matrix_ext_info),
55 ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
56 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
57 ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
58 ST_GYRO_DEFAULT_OUT_Y_L_ADDR,
59 st_gyro_mount_matrix_ext_info),
60 ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL,
61 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
62 ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
63 ST_GYRO_DEFAULT_OUT_Z_L_ADDR,
64 st_gyro_mount_matrix_ext_info),
65 IIO_CHAN_SOFT_TIMESTAMP(3)
66};
67
68static const struct st_sensor_settings st_gyro_sensors_settings[] = {
69 {
70 .wai = 0xd3,
71 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
72 .sensors_supported = {
73 [0] = L3G4200D_GYRO_DEV_NAME,
74 [1] = LSM330DL_GYRO_DEV_NAME,
75 },
76 .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
77 .odr = {
78 .addr = 0x20,
79 .mask = 0xc0,
80 .odr_avl = {
81 { .hz = 100, .value = 0x00, },
82 { .hz = 200, .value = 0x01, },
83 { .hz = 400, .value = 0x02, },
84 { .hz = 800, .value = 0x03, },
85 },
86 },
87 .pw = {
88 .addr = 0x20,
89 .mask = 0x08,
90 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
91 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
92 },
93 .enable_axis = {
94 .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
95 .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
96 },
97 .fs = {
98 .addr = 0x23,
99 .mask = 0x30,
100 .fs_avl = {
101 [0] = {
102 .num = ST_GYRO_FS_AVL_250DPS,
103 .value = 0x00,
104 .gain = IIO_DEGREE_TO_RAD(8750),
105 },
106 [1] = {
107 .num = ST_GYRO_FS_AVL_500DPS,
108 .value = 0x01,
109 .gain = IIO_DEGREE_TO_RAD(17500),
110 },
111 [2] = {
112 .num = ST_GYRO_FS_AVL_2000DPS,
113 .value = 0x02,
114 .gain = IIO_DEGREE_TO_RAD(70000),
115 },
116 },
117 },
118 .bdu = {
119 .addr = 0x23,
120 .mask = 0x80,
121 },
122 .drdy_irq = {
123 .int2 = {
124 .addr = 0x22,
125 .mask = 0x08,
126 },
127 /*
128 * The sensor has IHL (active low) and open
129 * drain settings, but only for INT1 and not
130 * for the DRDY line on INT2.
131 */
132 .stat_drdy = {
133 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
134 .mask = 0x07,
135 },
136 },
137 .sim = {
138 .addr = 0x23,
139 .value = BIT(0),
140 },
141 .multi_read_bit = true,
142 .bootime = 2,
143 },
144 {
145 .wai = 0xd4,
146 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
147 .sensors_supported = {
148 [0] = L3GD20_GYRO_DEV_NAME,
149 [1] = LSM330D_GYRO_DEV_NAME,
150 [2] = LSM330DLC_GYRO_DEV_NAME,
151 [3] = L3G4IS_GYRO_DEV_NAME,
152 [4] = LSM330_GYRO_DEV_NAME,
153 },
154 .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
155 .odr = {
156 .addr = 0x20,
157 .mask = 0xc0,
158 .odr_avl = {
159 { .hz = 95, .value = 0x00, },
160 { .hz = 190, .value = 0x01, },
161 { .hz = 380, .value = 0x02, },
162 { .hz = 760, .value = 0x03, },
163 },
164 },
165 .pw = {
166 .addr = 0x20,
167 .mask = 0x08,
168 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
169 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
170 },
171 .enable_axis = {
172 .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
173 .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
174 },
175 .fs = {
176 .addr = 0x23,
177 .mask = 0x30,
178 .fs_avl = {
179 [0] = {
180 .num = ST_GYRO_FS_AVL_250DPS,
181 .value = 0x00,
182 .gain = IIO_DEGREE_TO_RAD(8750),
183 },
184 [1] = {
185 .num = ST_GYRO_FS_AVL_500DPS,
186 .value = 0x01,
187 .gain = IIO_DEGREE_TO_RAD(17500),
188 },
189 [2] = {
190 .num = ST_GYRO_FS_AVL_2000DPS,
191 .value = 0x02,
192 .gain = IIO_DEGREE_TO_RAD(70000),
193 },
194 },
195 },
196 .bdu = {
197 .addr = 0x23,
198 .mask = 0x80,
199 },
200 .drdy_irq = {
201 .int2 = {
202 .addr = 0x22,
203 .mask = 0x08,
204 },
205 /*
206 * The sensor has IHL (active low) and open
207 * drain settings, but only for INT1 and not
208 * for the DRDY line on INT2.
209 */
210 .stat_drdy = {
211 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
212 .mask = 0x07,
213 },
214 },
215 .sim = {
216 .addr = 0x23,
217 .value = BIT(0),
218 },
219 .multi_read_bit = true,
220 .bootime = 2,
221 },
222 {
223 .wai = 0xd4,
224 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
225 .sensors_supported = {
226 [0] = LSM9DS0_GYRO_DEV_NAME,
227 },
228 .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
229 .odr = {
230 .addr = 0x20,
231 .mask = GENMASK(7, 6),
232 .odr_avl = {
233 { .hz = 95, .value = 0x00, },
234 { .hz = 190, .value = 0x01, },
235 { .hz = 380, .value = 0x02, },
236 { .hz = 760, .value = 0x03, },
237 },
238 },
239 .pw = {
240 .addr = 0x20,
241 .mask = BIT(3),
242 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
243 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
244 },
245 .enable_axis = {
246 .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
247 .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
248 },
249 .fs = {
250 .addr = 0x23,
251 .mask = GENMASK(5, 4),
252 .fs_avl = {
253 [0] = {
254 .num = ST_GYRO_FS_AVL_245DPS,
255 .value = 0x00,
256 .gain = IIO_DEGREE_TO_RAD(8750),
257 },
258 [1] = {
259 .num = ST_GYRO_FS_AVL_500DPS,
260 .value = 0x01,
261 .gain = IIO_DEGREE_TO_RAD(17500),
262 },
263 [2] = {
264 .num = ST_GYRO_FS_AVL_2000DPS,
265 .value = 0x02,
266 .gain = IIO_DEGREE_TO_RAD(70000),
267 },
268 },
269 },
270 .bdu = {
271 .addr = 0x23,
272 .mask = BIT(7),
273 },
274 .drdy_irq = {
275 .int2 = {
276 .addr = 0x22,
277 .mask = BIT(3),
278 },
279 /*
280 * The sensor has IHL (active low) and open
281 * drain settings, but only for INT1 and not
282 * for the DRDY line on INT2.
283 */
284 .stat_drdy = {
285 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
286 .mask = GENMASK(2, 0),
287 },
288 },
289 .sim = {
290 .addr = 0x23,
291 .value = BIT(0),
292 },
293 .multi_read_bit = true,
294 .bootime = 2,
295 },
296 {
297 .wai = 0xd7,
298 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
299 .sensors_supported = {
300 [0] = L3GD20H_GYRO_DEV_NAME,
301 },
302 .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
303 .odr = {
304 .addr = 0x20,
305 .mask = 0xc0,
306 .odr_avl = {
307 { .hz = 100, .value = 0x00, },
308 { .hz = 200, .value = 0x01, },
309 { .hz = 400, .value = 0x02, },
310 { .hz = 800, .value = 0x03, },
311 },
312 },
313 .pw = {
314 .addr = 0x20,
315 .mask = 0x08,
316 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
317 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
318 },
319 .enable_axis = {
320 .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
321 .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
322 },
323 .fs = {
324 .addr = 0x23,
325 .mask = 0x30,
326 .fs_avl = {
327 [0] = {
328 .num = ST_GYRO_FS_AVL_245DPS,
329 .value = 0x00,
330 .gain = IIO_DEGREE_TO_RAD(8750),
331 },
332 [1] = {
333 .num = ST_GYRO_FS_AVL_500DPS,
334 .value = 0x01,
335 .gain = IIO_DEGREE_TO_RAD(17500),
336 },
337 [2] = {
338 .num = ST_GYRO_FS_AVL_2000DPS,
339 .value = 0x02,
340 .gain = IIO_DEGREE_TO_RAD(70000),
341 },
342 },
343 },
344 .bdu = {
345 .addr = 0x23,
346 .mask = 0x80,
347 },
348 .drdy_irq = {
349 .int2 = {
350 .addr = 0x22,
351 .mask = 0x08,
352 },
353 /*
354 * The sensor has IHL (active low) and open
355 * drain settings, but only for INT1 and not
356 * for the DRDY line on INT2.
357 */
358 .stat_drdy = {
359 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
360 .mask = 0x07,
361 },
362 },
363 .sim = {
364 .addr = 0x23,
365 .value = BIT(0),
366 },
367 .multi_read_bit = true,
368 .bootime = 2,
369 },
370};
371
372/* DRDY on gyros is available only on INT2 pin */
373static const struct st_sensors_platform_data gyro_pdata = {
374 .drdy_int_pin = 2,
375};
376
377static int st_gyro_read_raw(struct iio_dev *indio_dev,
378 struct iio_chan_spec const *ch, int *val,
379 int *val2, long mask)
380{
381 int err;
382 struct st_sensor_data *gdata = iio_priv(indio_dev);
383
384 switch (mask) {
385 case IIO_CHAN_INFO_RAW:
386 err = st_sensors_read_info_raw(indio_dev, ch, val);
387 if (err < 0)
388 goto read_error;
389
390 return IIO_VAL_INT;
391 case IIO_CHAN_INFO_SCALE:
392 *val = 0;
393 *val2 = gdata->current_fullscale->gain;
394 return IIO_VAL_INT_PLUS_MICRO;
395 case IIO_CHAN_INFO_SAMP_FREQ:
396 *val = gdata->odr;
397 return IIO_VAL_INT;
398 default:
399 return -EINVAL;
400 }
401
402read_error:
403 return err;
404}
405
406static int st_gyro_write_raw(struct iio_dev *indio_dev,
407 struct iio_chan_spec const *chan, int val, int val2, long mask)
408{
409 switch (mask) {
410 case IIO_CHAN_INFO_SCALE:
411 return st_sensors_set_fullscale_by_gain(indio_dev, scale: val2);
412 case IIO_CHAN_INFO_SAMP_FREQ:
413 if (val2)
414 return -EINVAL;
415
416 return st_sensors_set_odr(indio_dev, odr: val);
417 default:
418 return -EINVAL;
419 }
420}
421
422static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
423static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
424
425static struct attribute *st_gyro_attributes[] = {
426 &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
427 &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
428 NULL,
429};
430
431static const struct attribute_group st_gyro_attribute_group = {
432 .attrs = st_gyro_attributes,
433};
434
435static const struct iio_info gyro_info = {
436 .attrs = &st_gyro_attribute_group,
437 .read_raw = &st_gyro_read_raw,
438 .write_raw = &st_gyro_write_raw,
439 .debugfs_reg_access = &st_sensors_debugfs_reg_access,
440};
441
442#ifdef CONFIG_IIO_TRIGGER
443static const struct iio_trigger_ops st_gyro_trigger_ops = {
444 .set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
445 .validate_device = st_sensors_validate_device,
446};
447#define ST_GYRO_TRIGGER_OPS (&st_gyro_trigger_ops)
448#else
449#define ST_GYRO_TRIGGER_OPS NULL
450#endif
451
452/*
453 * st_gyro_get_settings() - get sensor settings from device name
454 * @name: device name buffer reference.
455 *
456 * Return: valid reference on success, NULL otherwise.
457 */
458const struct st_sensor_settings *st_gyro_get_settings(const char *name)
459{
460 int index = st_sensors_get_settings_index(name,
461 list: st_gyro_sensors_settings,
462 ARRAY_SIZE(st_gyro_sensors_settings));
463 if (index < 0)
464 return NULL;
465
466 return &st_gyro_sensors_settings[index];
467}
468EXPORT_SYMBOL_NS(st_gyro_get_settings, IIO_ST_SENSORS);
469
470int st_gyro_common_probe(struct iio_dev *indio_dev)
471{
472 struct st_sensor_data *gdata = iio_priv(indio_dev);
473 struct st_sensors_platform_data *pdata;
474 struct device *parent = indio_dev->dev.parent;
475 int err;
476
477 indio_dev->modes = INDIO_DIRECT_MODE;
478 indio_dev->info = &gyro_info;
479
480 err = st_sensors_verify_id(indio_dev);
481 if (err < 0)
482 return err;
483
484 gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
485 indio_dev->channels = gdata->sensor_settings->ch;
486 indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
487
488 err = iio_read_mount_matrix(dev: parent, matrix: &gdata->mount_matrix);
489 if (err)
490 return err;
491
492 gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0];
493 gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz;
494
495 pdata = (struct st_sensors_platform_data *)&gyro_pdata;
496
497 err = st_sensors_init_sensor(indio_dev, pdata);
498 if (err < 0)
499 return err;
500
501 err = st_gyro_allocate_ring(indio_dev);
502 if (err < 0)
503 return err;
504
505 if (gdata->irq > 0) {
506 err = st_sensors_allocate_trigger(indio_dev,
507 ST_GYRO_TRIGGER_OPS);
508 if (err < 0)
509 return err;
510 }
511
512 return devm_iio_device_register(parent, indio_dev);
513}
514EXPORT_SYMBOL_NS(st_gyro_common_probe, IIO_ST_SENSORS);
515
516MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
517MODULE_DESCRIPTION("STMicroelectronics gyroscopes driver");
518MODULE_LICENSE("GPL v2");
519MODULE_IMPORT_NS(IIO_ST_SENSORS);
520

source code of linux/drivers/iio/gyro/st_gyro_core.c