// SPDX-License-Identifier: GPL-2.0-only /* * STMicroelectronics pressures driver * * Copyright 2013 STMicroelectronics Inc. * * Denis Ciocca <[email protected]> */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/sysfs.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/trigger.h> #include <linux/unaligned.h> #include <linux/iio/common/st_sensors.h> #include "st_pressure.h" /* * About determining pressure scaling factors * ------------------------------------------ * * Datasheets specify typical pressure sensitivity so that pressure is computed * according to the following equation : * pressure[mBar] = raw / sensitivity * where : * raw the 24 bits long raw sampled pressure * sensitivity a scaling factor specified by the datasheet in LSB/mBar * * IIO ABI expects pressure to be expressed as kPascal, hence pressure should be * computed according to : * pressure[kPascal] = pressure[mBar] / 10 * = raw / (sensitivity * 10) (1) * * Finally, st_press_read_raw() returns pressure scaling factor as an * IIO_VAL_INT_PLUS_NANO with a zero integral part and "gain" as decimal part. * Therefore, from (1), "gain" becomes : * gain = 10^9 / (sensitivity * 10) * = 10^8 / sensitivity * * About determining temperature scaling factors and offsets * --------------------------------------------------------- * * Datasheets specify typical temperature sensitivity and offset so that * temperature is computed according to the following equation : * temp[Celsius] = offset[Celsius] + (raw / sensitivity) * where : * raw the 16 bits long raw sampled temperature * offset a constant specified by the datasheet in degree Celsius * (sometimes zero) * sensitivity a scaling factor specified by the datasheet in LSB/Celsius * * IIO ABI expects temperature to be expressed as milli degree Celsius such as * user space should compute temperature according to : * temp[mCelsius] = temp[Celsius] * 10^3 * = (offset[Celsius] + (raw / sensitivity)) * 10^3 * = ((offset[Celsius] * sensitivity) + raw) * * (10^3 / sensitivity) (2) * * IIO ABI expects user space to apply offset and scaling factors to raw samples * according to : * temp[mCelsius] = (OFFSET + raw) * SCALE * where : * OFFSET an arbitrary constant exposed by device * SCALE an arbitrary scaling factor exposed by device * * Matching OFFSET and SCALE with members of (2) gives : * OFFSET = offset[Celsius] * sensitivity (3) * SCALE = 10^3 / sensitivity (4) * * st_press_read_raw() returns temperature scaling factor as an * IIO_VAL_FRACTIONAL with a 10^3 numerator and "gain2" as denominator. * Therefore, from (3), "gain2" becomes : * gain2 = sensitivity * * When declared within channel, i.e. for a non zero specified offset, * st_press_read_raw() will return the latter as an IIO_VAL_FRACTIONAL such as : * numerator = OFFSET * 10^3 * denominator = 10^3 * giving from (4): * numerator = offset[Celsius] * 10^3 * sensitivity * = offset[mCelsius] * gain2 */ #define MCELSIUS_PER_CELSIUS … /* Default pressure sensitivity */ #define ST_PRESS_LSB_PER_MBAR … #define ST_PRESS_KPASCAL_NANO_SCALE … /* Default temperature sensitivity */ #define ST_PRESS_LSB_PER_CELSIUS … #define ST_PRESS_MILLI_CELSIUS_OFFSET … /* FULLSCALE */ #define ST_PRESS_FS_AVL_1100MB … #define ST_PRESS_FS_AVL_1260MB … #define ST_PRESS_1_OUT_XL_ADDR … #define ST_TEMP_1_OUT_L_ADDR … /* LPS001WP pressure resolution */ #define ST_PRESS_LPS001WP_LSB_PER_MBAR … /* LPS001WP temperature resolution */ #define ST_PRESS_LPS001WP_LSB_PER_CELSIUS … /* LPS001WP pressure gain */ #define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN … /* LPS001WP pressure and temp L addresses */ #define ST_PRESS_LPS001WP_OUT_L_ADDR … #define ST_TEMP_LPS001WP_OUT_L_ADDR … /* LPS25H pressure and temp L addresses */ #define ST_PRESS_LPS25H_OUT_XL_ADDR … #define ST_TEMP_LPS25H_OUT_L_ADDR … /* LPS22HB temperature sensitivity */ #define ST_PRESS_LPS22HB_LSB_PER_CELSIUS … static const struct iio_chan_spec st_press_1_channels[] = …; static const struct iio_chan_spec st_press_lps001wp_channels[] = …; static const struct iio_chan_spec st_press_lps22hb_channels[] = …; static const struct st_sensor_settings st_press_sensors_settings[] = …; static int st_press_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask) { … } static int st_press_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) { … } static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL(); static struct attribute *st_press_attributes[] = …; static const struct attribute_group st_press_attribute_group = …; static const struct iio_info press_info = …; #ifdef CONFIG_IIO_TRIGGER static const struct iio_trigger_ops st_press_trigger_ops = …; #define ST_PRESS_TRIGGER_OPS … #else #define ST_PRESS_TRIGGER_OPS … #endif /* * st_press_get_settings() - get sensor settings from device name * @name: device name buffer reference. * * Return: valid reference on success, NULL otherwise. */ const struct st_sensor_settings *st_press_get_settings(const char *name) { … } EXPORT_SYMBOL_NS(…); int st_press_common_probe(struct iio_dev *indio_dev) { … } EXPORT_SYMBOL_NS(…); MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_IMPORT_NS(…);