File Index
Files and directories
Sign in
FILE

st_gyro_core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/gyro/st_gyro_core.c 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
 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, 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
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					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(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}
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");
~/ Read-only file preview.