Linux 6.9-rc6
[sfrench/cifs-2.6.git] / drivers / iio / gyro / st_gyro_core.c
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
35 static const struct iio_mount_matrix *
36 st_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
44 static 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
49 static 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
68 static 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 */
373 static const struct st_sensors_platform_data gyro_pdata = {
374         .drdy_int_pin = 2,
375 };
376
377 static 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
402 read_error:
403         return err;
404 }
405
406 static 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, val2);
412         case IIO_CHAN_INFO_SAMP_FREQ:
413                 if (val2)
414                         return -EINVAL;
415
416                 return st_sensors_set_odr(indio_dev, val);
417         default:
418                 return -EINVAL;
419         }
420 }
421
422 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
423 static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
424
425 static 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
431 static const struct attribute_group st_gyro_attribute_group = {
432         .attrs = st_gyro_attributes,
433 };
434
435 static 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
443 static 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  */
458 const struct st_sensor_settings *st_gyro_get_settings(const char *name)
459 {
460         int index = st_sensors_get_settings_index(name,
461                                         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 }
468 EXPORT_SYMBOL_NS(st_gyro_get_settings, IIO_ST_SENSORS);
469
470 int 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(parent, &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 }
514 EXPORT_SYMBOL_NS(st_gyro_common_probe, IIO_ST_SENSORS);
515
516 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
517 MODULE_DESCRIPTION("STMicroelectronics gyroscopes driver");
518 MODULE_LICENSE("GPL v2");
519 MODULE_IMPORT_NS(IIO_ST_SENSORS);