xref: /linux/drivers/iio/gyro/st_gyro_core.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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 *
st_gyro_get_mount_matrix(const struct iio_dev * indio_dev,const struct iio_chan_spec * chan)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 
st_gyro_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * ch,int * val,int * val2,long mask)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 
st_gyro_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)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  */
st_gyro_get_settings(const char * name)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 
st_gyro_common_probe(struct iio_dev * indio_dev)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);
520