• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * STMicroelectronics pressures driver
4  *
5  * Copyright 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/sysfs.h>
14 #include <linux/iio/iio.h>
15 #include <linux/iio/sysfs.h>
16 #include <linux/iio/trigger.h>
17 #include <asm/unaligned.h>
18 
19 #include <linux/iio/common/st_sensors.h>
20 #include "st_pressure.h"
21 
22 /*
23  * About determining pressure scaling factors
24  * ------------------------------------------
25  *
26  * Datasheets specify typical pressure sensitivity so that pressure is computed
27  * according to the following equation :
28  *     pressure[mBar] = raw / sensitivity
29  * where :
30  *     raw          the 24 bits long raw sampled pressure
31  *     sensitivity  a scaling factor specified by the datasheet in LSB/mBar
32  *
33  * IIO ABI expects pressure to be expressed as kPascal, hence pressure should be
34  * computed according to :
35  *     pressure[kPascal] = pressure[mBar] / 10
36  *                       = raw / (sensitivity * 10)                          (1)
37  *
38  * Finally, st_press_read_raw() returns pressure scaling factor as an
39  * IIO_VAL_INT_PLUS_NANO with a zero integral part and "gain" as decimal part.
40  * Therefore, from (1), "gain" becomes :
41  *     gain = 10^9 / (sensitivity * 10)
42  *          = 10^8 / sensitivity
43  *
44  * About determining temperature scaling factors and offsets
45  * ---------------------------------------------------------
46  *
47  * Datasheets specify typical temperature sensitivity and offset so that
48  * temperature is computed according to the following equation :
49  *     temp[Celsius] = offset[Celsius] + (raw / sensitivity)
50  * where :
51  *     raw          the 16 bits long raw sampled temperature
52  *     offset       a constant specified by the datasheet in degree Celsius
53  *                  (sometimes zero)
54  *     sensitivity  a scaling factor specified by the datasheet in LSB/Celsius
55  *
56  * IIO ABI expects temperature to be expressed as milli degree Celsius such as
57  * user space should compute temperature according to :
58  *     temp[mCelsius] = temp[Celsius] * 10^3
59  *                    = (offset[Celsius] + (raw / sensitivity)) * 10^3
60  *                    = ((offset[Celsius] * sensitivity) + raw) *
61  *                      (10^3 / sensitivity)                                 (2)
62  *
63  * IIO ABI expects user space to apply offset and scaling factors to raw samples
64  * according to :
65  *     temp[mCelsius] = (OFFSET + raw) * SCALE
66  * where :
67  *     OFFSET an arbitrary constant exposed by device
68  *     SCALE  an arbitrary scaling factor exposed by device
69  *
70  * Matching OFFSET and SCALE with members of (2) gives :
71  *     OFFSET = offset[Celsius] * sensitivity                                (3)
72  *     SCALE  = 10^3 / sensitivity                                           (4)
73  *
74  * st_press_read_raw() returns temperature scaling factor as an
75  * IIO_VAL_FRACTIONAL with a 10^3 numerator and "gain2" as denominator.
76  * Therefore, from (3), "gain2" becomes :
77  *     gain2 = sensitivity
78  *
79  * When declared within channel, i.e. for a non zero specified offset,
80  * st_press_read_raw() will return the latter as an IIO_VAL_FRACTIONAL such as :
81  *     numerator = OFFSET * 10^3
82  *     denominator = 10^3
83  * giving from (4):
84  *     numerator = offset[Celsius] * 10^3 * sensitivity
85  *               = offset[mCelsius] * gain2
86  */
87 
88 #define MCELSIUS_PER_CELSIUS			1000
89 
90 /* Default pressure sensitivity */
91 #define ST_PRESS_LSB_PER_MBAR			4096UL
92 #define ST_PRESS_KPASCAL_NANO_SCALE		(100000000UL / \
93 						 ST_PRESS_LSB_PER_MBAR)
94 
95 /* Default temperature sensitivity */
96 #define ST_PRESS_LSB_PER_CELSIUS		480UL
97 #define ST_PRESS_MILLI_CELSIUS_OFFSET		42500UL
98 
99 /* FULLSCALE */
100 #define ST_PRESS_FS_AVL_1100MB			1100
101 #define ST_PRESS_FS_AVL_1260MB			1260
102 
103 #define ST_PRESS_1_OUT_XL_ADDR			0x28
104 #define ST_TEMP_1_OUT_L_ADDR			0x2b
105 
106 /* LPS001WP pressure resolution */
107 #define ST_PRESS_LPS001WP_LSB_PER_MBAR		16UL
108 /* LPS001WP temperature resolution */
109 #define ST_PRESS_LPS001WP_LSB_PER_CELSIUS	64UL
110 /* LPS001WP pressure gain */
111 #define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \
112 	(100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR)
113 /* LPS001WP pressure and temp L addresses */
114 #define ST_PRESS_LPS001WP_OUT_L_ADDR		0x28
115 #define ST_TEMP_LPS001WP_OUT_L_ADDR		0x2a
116 
117 /* LPS25H pressure and temp L addresses */
118 #define ST_PRESS_LPS25H_OUT_XL_ADDR		0x28
119 #define ST_TEMP_LPS25H_OUT_L_ADDR		0x2b
120 
121 /* LPS22HB temperature sensitivity */
122 #define ST_PRESS_LPS22HB_LSB_PER_CELSIUS	100UL
123 
124 static const struct iio_chan_spec st_press_1_channels[] = {
125 	{
126 		.type = IIO_PRESSURE,
127 		.address = ST_PRESS_1_OUT_XL_ADDR,
128 		.scan_index = 0,
129 		.scan_type = {
130 			.sign = 's',
131 			.realbits = 24,
132 			.storagebits = 32,
133 			.endianness = IIO_LE,
134 		},
135 		.info_mask_separate =
136 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
137 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
138 	},
139 	{
140 		.type = IIO_TEMP,
141 		.address = ST_TEMP_1_OUT_L_ADDR,
142 		.scan_index = 1,
143 		.scan_type = {
144 			.sign = 's',
145 			.realbits = 16,
146 			.storagebits = 16,
147 			.endianness = IIO_LE,
148 		},
149 		.info_mask_separate =
150 			BIT(IIO_CHAN_INFO_RAW) |
151 			BIT(IIO_CHAN_INFO_SCALE) |
152 			BIT(IIO_CHAN_INFO_OFFSET),
153 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
154 	},
155 	IIO_CHAN_SOFT_TIMESTAMP(2)
156 };
157 
158 static const struct iio_chan_spec st_press_lps001wp_channels[] = {
159 	{
160 		.type = IIO_PRESSURE,
161 		.address = ST_PRESS_LPS001WP_OUT_L_ADDR,
162 		.scan_index = 0,
163 		.scan_type = {
164 			.sign = 's',
165 			.realbits = 16,
166 			.storagebits = 16,
167 			.endianness = IIO_LE,
168 		},
169 		.info_mask_separate =
170 			BIT(IIO_CHAN_INFO_RAW) |
171 			BIT(IIO_CHAN_INFO_SCALE),
172 	},
173 	{
174 		.type = IIO_TEMP,
175 		.address = ST_TEMP_LPS001WP_OUT_L_ADDR,
176 		.scan_index = 1,
177 		.scan_type = {
178 			.sign = 's',
179 			.realbits = 16,
180 			.storagebits = 16,
181 			.endianness = IIO_LE,
182 		},
183 		.info_mask_separate =
184 			BIT(IIO_CHAN_INFO_RAW) |
185 			BIT(IIO_CHAN_INFO_SCALE),
186 	},
187 	IIO_CHAN_SOFT_TIMESTAMP(2)
188 };
189 
190 static const struct iio_chan_spec st_press_lps22hb_channels[] = {
191 	{
192 		.type = IIO_PRESSURE,
193 		.address = ST_PRESS_1_OUT_XL_ADDR,
194 		.scan_index = 0,
195 		.scan_type = {
196 			.sign = 's',
197 			.realbits = 24,
198 			.storagebits = 32,
199 			.endianness = IIO_LE,
200 		},
201 		.info_mask_separate =
202 			BIT(IIO_CHAN_INFO_RAW) |
203 			BIT(IIO_CHAN_INFO_SCALE),
204 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
205 	},
206 	{
207 		.type = IIO_TEMP,
208 		.address = ST_TEMP_1_OUT_L_ADDR,
209 		.scan_index = 1,
210 		.scan_type = {
211 			.sign = 's',
212 			.realbits = 16,
213 			.storagebits = 16,
214 			.endianness = IIO_LE,
215 		},
216 		.info_mask_separate =
217 			BIT(IIO_CHAN_INFO_RAW) |
218 			BIT(IIO_CHAN_INFO_SCALE),
219 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
220 	},
221 	IIO_CHAN_SOFT_TIMESTAMP(2)
222 };
223 
224 static const struct st_sensor_settings st_press_sensors_settings[] = {
225 	{
226 		/*
227 		 * CUSTOM VALUES FOR LPS331AP SENSOR
228 		 * See LPS331AP datasheet:
229 		 * http://www2.st.com/resource/en/datasheet/lps331ap.pdf
230 		 */
231 		.wai = 0xbb,
232 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
233 		.sensors_supported = {
234 			[0] = LPS331AP_PRESS_DEV_NAME,
235 		},
236 		.ch = (struct iio_chan_spec *)st_press_1_channels,
237 		.num_ch = ARRAY_SIZE(st_press_1_channels),
238 		.odr = {
239 			.addr = 0x20,
240 			.mask = 0x70,
241 			.odr_avl = {
242 				{ .hz = 1, .value = 0x01 },
243 				{ .hz = 7, .value = 0x05 },
244 				{ .hz = 13, .value = 0x06 },
245 				{ .hz = 25, .value = 0x07 },
246 			},
247 		},
248 		.pw = {
249 			.addr = 0x20,
250 			.mask = 0x80,
251 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
252 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
253 		},
254 		.fs = {
255 			.addr = 0x23,
256 			.mask = 0x30,
257 			.fs_avl = {
258 				/*
259 				 * Pressure and temperature sensitivity values
260 				 * as defined in table 3 of LPS331AP datasheet.
261 				 */
262 				[0] = {
263 					.num = ST_PRESS_FS_AVL_1260MB,
264 					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
265 					.gain2 = ST_PRESS_LSB_PER_CELSIUS,
266 				},
267 			},
268 		},
269 		.bdu = {
270 			.addr = 0x20,
271 			.mask = 0x04,
272 		},
273 		.drdy_irq = {
274 			.int1 = {
275 				.addr = 0x22,
276 				.mask = 0x04,
277 				.addr_od = 0x22,
278 				.mask_od = 0x40,
279 			},
280 			.int2 = {
281 				.addr = 0x22,
282 				.mask = 0x20,
283 				.addr_od = 0x22,
284 				.mask_od = 0x40,
285 			},
286 			.addr_ihl = 0x22,
287 			.mask_ihl = 0x80,
288 			.stat_drdy = {
289 				.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
290 				.mask = 0x03,
291 			},
292 		},
293 		.sim = {
294 			.addr = 0x20,
295 			.value = BIT(0),
296 		},
297 		.multi_read_bit = true,
298 		.bootime = 2,
299 	},
300 	{
301 		/*
302 		 * CUSTOM VALUES FOR LPS001WP SENSOR
303 		 */
304 		.wai = 0xba,
305 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
306 		.sensors_supported = {
307 			[0] = LPS001WP_PRESS_DEV_NAME,
308 		},
309 		.ch = (struct iio_chan_spec *)st_press_lps001wp_channels,
310 		.num_ch = ARRAY_SIZE(st_press_lps001wp_channels),
311 		.odr = {
312 			.addr = 0x20,
313 			.mask = 0x30,
314 			.odr_avl = {
315 				{ .hz = 1, .value = 0x01 },
316 				{ .hz = 7, .value = 0x02 },
317 				{ .hz = 13, .value = 0x03 },
318 			},
319 		},
320 		.pw = {
321 			.addr = 0x20,
322 			.mask = 0x40,
323 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
324 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
325 		},
326 		.fs = {
327 			.fs_avl = {
328 				/*
329 				 * Pressure and temperature resolution values
330 				 * as defined in table 3 of LPS001WP datasheet.
331 				 */
332 				[0] = {
333 					.num = ST_PRESS_FS_AVL_1100MB,
334 					.gain = ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN,
335 					.gain2 = ST_PRESS_LPS001WP_LSB_PER_CELSIUS,
336 				},
337 			},
338 		},
339 		.bdu = {
340 			.addr = 0x20,
341 			.mask = 0x04,
342 		},
343 		.sim = {
344 			.addr = 0x20,
345 			.value = BIT(0),
346 		},
347 		.multi_read_bit = true,
348 		.bootime = 2,
349 	},
350 	{
351 		/*
352 		 * CUSTOM VALUES FOR LPS25H SENSOR
353 		 * See LPS25H datasheet:
354 		 * http://www2.st.com/resource/en/datasheet/lps25h.pdf
355 		 */
356 		.wai = 0xbd,
357 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
358 		.sensors_supported = {
359 			[0] = LPS25H_PRESS_DEV_NAME,
360 		},
361 		.ch = (struct iio_chan_spec *)st_press_1_channels,
362 		.num_ch = ARRAY_SIZE(st_press_1_channels),
363 		.odr = {
364 			.addr = 0x20,
365 			.mask = 0x70,
366 			.odr_avl = {
367 				{ .hz = 1, .value = 0x01 },
368 				{ .hz = 7, .value = 0x02 },
369 				{ .hz = 13, .value = 0x03 },
370 				{ .hz = 25, .value = 0x04 },
371 			},
372 		},
373 		.pw = {
374 			.addr = 0x20,
375 			.mask = 0x80,
376 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
377 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
378 		},
379 		.fs = {
380 			.fs_avl = {
381 				/*
382 				 * Pressure and temperature sensitivity values
383 				 * as defined in table 3 of LPS25H datasheet.
384 				 */
385 				[0] = {
386 					.num = ST_PRESS_FS_AVL_1260MB,
387 					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
388 					.gain2 = ST_PRESS_LSB_PER_CELSIUS,
389 				},
390 			},
391 		},
392 		.bdu = {
393 			.addr = 0x20,
394 			.mask = 0x04,
395 		},
396 		.drdy_irq = {
397 			.int1 = {
398 				.addr = 0x23,
399 				.mask = 0x01,
400 				.addr_od = 0x22,
401 				.mask_od = 0x40,
402 			},
403 			.addr_ihl = 0x22,
404 			.mask_ihl = 0x80,
405 			.stat_drdy = {
406 				.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
407 				.mask = 0x03,
408 			},
409 		},
410 		.sim = {
411 			.addr = 0x20,
412 			.value = BIT(0),
413 		},
414 		.multi_read_bit = true,
415 		.bootime = 2,
416 	},
417 	{
418 		/*
419 		 * CUSTOM VALUES FOR LPS22HB SENSOR
420 		 * See LPS22HB datasheet:
421 		 * http://www2.st.com/resource/en/datasheet/lps22hb.pdf
422 		 */
423 		.wai = 0xb1,
424 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
425 		.sensors_supported = {
426 			[0] = LPS22HB_PRESS_DEV_NAME,
427 			[1] = LPS33HW_PRESS_DEV_NAME,
428 			[2] = LPS35HW_PRESS_DEV_NAME,
429 		},
430 		.ch = (struct iio_chan_spec *)st_press_lps22hb_channels,
431 		.num_ch = ARRAY_SIZE(st_press_lps22hb_channels),
432 		.odr = {
433 			.addr = 0x10,
434 			.mask = 0x70,
435 			.odr_avl = {
436 				{ .hz = 1, .value = 0x01 },
437 				{ .hz = 10, .value = 0x02 },
438 				{ .hz = 25, .value = 0x03 },
439 				{ .hz = 50, .value = 0x04 },
440 				{ .hz = 75, .value = 0x05 },
441 			},
442 		},
443 		.pw = {
444 			.addr = 0x10,
445 			.mask = 0x70,
446 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
447 		},
448 		.fs = {
449 			.fs_avl = {
450 				/*
451 				 * Pressure and temperature sensitivity values
452 				 * as defined in table 3 of LPS22HB datasheet.
453 				 */
454 				[0] = {
455 					.num = ST_PRESS_FS_AVL_1260MB,
456 					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
457 					.gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS,
458 				},
459 			},
460 		},
461 		.bdu = {
462 			.addr = 0x10,
463 			.mask = 0x02,
464 		},
465 		.drdy_irq = {
466 			.int1 = {
467 				.addr = 0x12,
468 				.mask = 0x04,
469 				.addr_od = 0x12,
470 				.mask_od = 0x40,
471 			},
472 			.addr_ihl = 0x12,
473 			.mask_ihl = 0x80,
474 			.stat_drdy = {
475 				.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
476 				.mask = 0x03,
477 			},
478 		},
479 		.sim = {
480 			.addr = 0x10,
481 			.value = BIT(0),
482 		},
483 		.multi_read_bit = false,
484 		.bootime = 2,
485 	},
486 	{
487 		/*
488 		 * CUSTOM VALUES FOR LPS22HH SENSOR
489 		 * See LPS22HH datasheet:
490 		 * http://www2.st.com/resource/en/datasheet/lps22hh.pdf
491 		 */
492 		.wai = 0xb3,
493 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
494 		.sensors_supported = {
495 			[0] = LPS22HH_PRESS_DEV_NAME,
496 		},
497 		.ch = (struct iio_chan_spec *)st_press_lps22hb_channels,
498 		.num_ch = ARRAY_SIZE(st_press_lps22hb_channels),
499 		.odr = {
500 			.addr = 0x10,
501 			.mask = 0x70,
502 			.odr_avl = {
503 				{ .hz = 1, .value = 0x01 },
504 				{ .hz = 10, .value = 0x02 },
505 				{ .hz = 25, .value = 0x03 },
506 				{ .hz = 50, .value = 0x04 },
507 				{ .hz = 75, .value = 0x05 },
508 				{ .hz = 100, .value = 0x06 },
509 				{ .hz = 200, .value = 0x07 },
510 			},
511 		},
512 		.pw = {
513 			.addr = 0x10,
514 			.mask = 0x70,
515 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
516 		},
517 		.fs = {
518 			.fs_avl = {
519 				/*
520 				 * Pressure and temperature sensitivity values
521 				 * as defined in table 3 of LPS22HH datasheet.
522 				 */
523 				[0] = {
524 					.num = ST_PRESS_FS_AVL_1260MB,
525 					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
526 					.gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS,
527 				},
528 			},
529 		},
530 		.bdu = {
531 			.addr = 0x10,
532 			.mask = BIT(1),
533 		},
534 		.drdy_irq = {
535 			.int1 = {
536 				.addr = 0x12,
537 				.mask = BIT(2),
538 				.addr_od = 0x11,
539 				.mask_od = BIT(5),
540 			},
541 			.addr_ihl = 0x11,
542 			.mask_ihl = BIT(6),
543 			.stat_drdy = {
544 				.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
545 				.mask = 0x03,
546 			},
547 		},
548 		.sim = {
549 			.addr = 0x10,
550 			.value = BIT(0),
551 		},
552 		.multi_read_bit = false,
553 		.bootime = 2,
554 	},
555 	{
556 		/*
557 		 * CUSTOM VALUES FOR LPS22DF SENSOR
558 		 * See LPS22DF datasheet:
559 		 * http://www.st.com/resource/en/datasheet/lps22df.pdf
560 		 */
561 		.wai = 0xb4,
562 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
563 		.sensors_supported = {
564 			[0] = LPS22DF_PRESS_DEV_NAME,
565 		},
566 		.ch = (struct iio_chan_spec *)st_press_lps22hb_channels,
567 		.num_ch = ARRAY_SIZE(st_press_lps22hb_channels),
568 		.odr = {
569 			.addr = 0x10,
570 			.mask = 0x78,
571 			.odr_avl = {
572 				{ .hz = 1, .value = 0x01 },
573 				{ .hz = 4, .value = 0x02 },
574 				{ .hz = 10, .value = 0x03 },
575 				{ .hz = 25, .value = 0x04 },
576 				{ .hz = 50, .value = 0x05 },
577 				{ .hz = 75, .value = 0x06 },
578 				{ .hz = 100, .value = 0x07 },
579 				{ .hz = 200, .value = 0x08 },
580 			},
581 		},
582 		.pw = {
583 			.addr = 0x10,
584 			.mask = 0x78,
585 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
586 		},
587 		.fs = {
588 			.fs_avl = {
589 				/*
590 				 * Pressure and temperature sensitivity values
591 				 * as defined in table 2 of LPS22DF datasheet.
592 				 */
593 				[0] = {
594 					.num = ST_PRESS_FS_AVL_1260MB,
595 					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
596 					.gain2 = ST_PRESS_LPS22HB_LSB_PER_CELSIUS,
597 				},
598 			},
599 		},
600 		.bdu = {
601 			.addr = 0x11,
602 			.mask = BIT(3),
603 		},
604 		.drdy_irq = {
605 			.int1 = {
606 				.addr = 0x13,
607 				.mask = BIT(5),
608 				.addr_od = 0x12,
609 				.mask_od = BIT(1),
610 			},
611 			.addr_ihl = 0x12,
612 			.mask_ihl = BIT(3),
613 			.stat_drdy = {
614 				.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
615 				.mask = 0x03,
616 			},
617 		},
618 		.sim = {
619 			.addr = 0x0E,
620 			.value = BIT(5),
621 		},
622 		.multi_read_bit = false,
623 		.bootime = 2,
624 	},
625 };
626 
st_press_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * ch,int val,int val2,long mask)627 static int st_press_write_raw(struct iio_dev *indio_dev,
628 			      struct iio_chan_spec const *ch,
629 			      int val,
630 			      int val2,
631 			      long mask)
632 {
633 	switch (mask) {
634 	case IIO_CHAN_INFO_SAMP_FREQ:
635 		if (val2)
636 			return -EINVAL;
637 
638 		return st_sensors_set_odr(indio_dev, val);
639 	default:
640 		return -EINVAL;
641 	}
642 }
643 
st_press_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * ch,int * val,int * val2,long mask)644 static int st_press_read_raw(struct iio_dev *indio_dev,
645 			struct iio_chan_spec const *ch, int *val,
646 							int *val2, long mask)
647 {
648 	int err;
649 	struct st_sensor_data *press_data = iio_priv(indio_dev);
650 
651 	switch (mask) {
652 	case IIO_CHAN_INFO_RAW:
653 		err = st_sensors_read_info_raw(indio_dev, ch, val);
654 		if (err < 0)
655 			goto read_error;
656 
657 		return IIO_VAL_INT;
658 	case IIO_CHAN_INFO_SCALE:
659 		switch (ch->type) {
660 		case IIO_PRESSURE:
661 			*val = 0;
662 			*val2 = press_data->current_fullscale->gain;
663 			return IIO_VAL_INT_PLUS_NANO;
664 		case IIO_TEMP:
665 			*val = MCELSIUS_PER_CELSIUS;
666 			*val2 = press_data->current_fullscale->gain2;
667 			return IIO_VAL_FRACTIONAL;
668 		default:
669 			err = -EINVAL;
670 			goto read_error;
671 		}
672 
673 	case IIO_CHAN_INFO_OFFSET:
674 		switch (ch->type) {
675 		case IIO_TEMP:
676 			*val = ST_PRESS_MILLI_CELSIUS_OFFSET *
677 			       press_data->current_fullscale->gain2;
678 			*val2 = MCELSIUS_PER_CELSIUS;
679 			break;
680 		default:
681 			err = -EINVAL;
682 			goto read_error;
683 		}
684 
685 		return IIO_VAL_FRACTIONAL;
686 	case IIO_CHAN_INFO_SAMP_FREQ:
687 		*val = press_data->odr;
688 		return IIO_VAL_INT;
689 	default:
690 		return -EINVAL;
691 	}
692 
693 read_error:
694 	return err;
695 }
696 
697 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
698 
699 static struct attribute *st_press_attributes[] = {
700 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
701 	NULL,
702 };
703 
704 static const struct attribute_group st_press_attribute_group = {
705 	.attrs = st_press_attributes,
706 };
707 
708 static const struct iio_info press_info = {
709 	.attrs = &st_press_attribute_group,
710 	.read_raw = &st_press_read_raw,
711 	.write_raw = &st_press_write_raw,
712 	.debugfs_reg_access = &st_sensors_debugfs_reg_access,
713 };
714 
715 #ifdef CONFIG_IIO_TRIGGER
716 static const struct iio_trigger_ops st_press_trigger_ops = {
717 	.set_trigger_state = ST_PRESS_TRIGGER_SET_STATE,
718 	.validate_device = st_sensors_validate_device,
719 };
720 #define ST_PRESS_TRIGGER_OPS (&st_press_trigger_ops)
721 #else
722 #define ST_PRESS_TRIGGER_OPS NULL
723 #endif
724 
725 /*
726  * st_press_get_settings() - get sensor settings from device name
727  * @name: device name buffer reference.
728  *
729  * Return: valid reference on success, NULL otherwise.
730  */
st_press_get_settings(const char * name)731 const struct st_sensor_settings *st_press_get_settings(const char *name)
732 {
733 	int index = st_sensors_get_settings_index(name,
734 					st_press_sensors_settings,
735 					ARRAY_SIZE(st_press_sensors_settings));
736 	if (index < 0)
737 		return NULL;
738 
739 	return &st_press_sensors_settings[index];
740 }
741 EXPORT_SYMBOL_NS(st_press_get_settings, IIO_ST_SENSORS);
742 
st_press_common_probe(struct iio_dev * indio_dev)743 int st_press_common_probe(struct iio_dev *indio_dev)
744 {
745 	struct st_sensor_data *press_data = iio_priv(indio_dev);
746 	struct device *parent = indio_dev->dev.parent;
747 	struct st_sensors_platform_data *pdata = dev_get_platdata(parent);
748 	int err;
749 
750 	indio_dev->modes = INDIO_DIRECT_MODE;
751 	indio_dev->info = &press_info;
752 
753 	err = st_sensors_verify_id(indio_dev);
754 	if (err < 0)
755 		return err;
756 
757 	/*
758 	 * Skip timestamping channel while declaring available channels to
759 	 * common st_sensor layer. Look at st_sensors_get_buffer_element() to
760 	 * see how timestamps are explicitly pushed as last samples block
761 	 * element.
762 	 */
763 	press_data->num_data_channels = press_data->sensor_settings->num_ch - 1;
764 	indio_dev->channels = press_data->sensor_settings->ch;
765 	indio_dev->num_channels = press_data->sensor_settings->num_ch;
766 
767 	press_data->current_fullscale = &press_data->sensor_settings->fs.fs_avl[0];
768 
769 	press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz;
770 
771 	/* Some devices don't support a data ready pin. */
772 	if (!pdata && (press_data->sensor_settings->drdy_irq.int1.addr ||
773 		       press_data->sensor_settings->drdy_irq.int2.addr))
774 		pdata =	(struct st_sensors_platform_data *)&default_press_pdata;
775 
776 	err = st_sensors_init_sensor(indio_dev, pdata);
777 	if (err < 0)
778 		return err;
779 
780 	err = st_press_allocate_ring(indio_dev);
781 	if (err < 0)
782 		return err;
783 
784 	if (press_data->irq > 0) {
785 		err = st_sensors_allocate_trigger(indio_dev,
786 						  ST_PRESS_TRIGGER_OPS);
787 		if (err < 0)
788 			return err;
789 	}
790 
791 	return devm_iio_device_register(parent, indio_dev);
792 }
793 EXPORT_SYMBOL_NS(st_press_common_probe, IIO_ST_SENSORS);
794 
795 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
796 MODULE_DESCRIPTION("STMicroelectronics pressures driver");
797 MODULE_LICENSE("GPL v2");
798 MODULE_IMPORT_NS(IIO_ST_SENSORS);
799