| Author | Tokens | Token Proportion | Commits | Commit Proportion |
|---|---|---|---|---|
| Francesco Lavra | 767 | 74.11% | 1 | 5.26% |
| Lorenzo Bianconi | 207 | 20.00% | 14 | 73.68% |
| Martin Kepplinger | 40 | 3.86% | 1 | 5.26% |
| mario tesi | 12 | 1.16% | 1 | 5.26% |
| Sean Nyekjaer | 8 | 0.77% | 1 | 5.26% |
| Thomas Gleixner | 1 | 0.10% | 1 | 5.26% |
| Total | 1035 | 19 |
// SPDX-License-Identifier: GPL-2.0-only /* * STMicroelectronics st_lsm6dsx IMU sensor fusion * * Copyright 2026 BayLibre, SAS */ #include <linux/cleanup.h> #include <linux/errno.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/mutex.h> #include <linux/regmap.h> #include <linux/sprintf.h> #include <linux/types.h> #include <linux/units.h> #include "st_lsm6dsx.h" static int st_lsm6dsx_fusion_get_odr_val(const struct st_lsm6dsx_fusion_settings *settings, u32 odr_mHz, u8 *val) { int odr_hz = odr_mHz / MILLI; int i; for (i = 0; i < settings->odr_len; i++) { if (settings->odr_hz[i] == odr_hz) break; } if (i == settings->odr_len) return -EINVAL; *val = i; return 0; } /** * st_lsm6dsx_fusion_page_enable - Enable access to sensor fusion configuration * registers. * @hw: Sensor hardware instance. * * Return: 0 on success, negative value on error. */ static int st_lsm6dsx_fusion_page_enable(struct st_lsm6dsx_hw *hw) { const struct st_lsm6dsx_reg *mux; mux = &hw->settings->fusion_settings.page_mux; return regmap_set_bits(hw->regmap, mux->addr, mux->mask); } /** * st_lsm6dsx_fusion_page_disable - Disable access to sensor fusion * configuration registers. * @hw: Sensor hardware instance. * * Return: 0 on success, negative value on error. */ static int st_lsm6dsx_fusion_page_disable(struct st_lsm6dsx_hw *hw) { const struct st_lsm6dsx_reg *mux; mux = &hw->settings->fusion_settings.page_mux; return regmap_clear_bits(hw->regmap, mux->addr, mux->mask); } static int st_lsm6dsx_fusion_set_odr_locked(struct st_lsm6dsx_sensor *sensor, bool enable) { const struct st_lsm6dsx_fusion_settings *settings; struct st_lsm6dsx_hw *hw = sensor->hw; int err; settings = &hw->settings->fusion_settings; if (enable) { const struct st_lsm6dsx_reg *reg = &settings->odr_reg; u8 odr_val; u8 data; st_lsm6dsx_fusion_get_odr_val(settings, sensor->hwfifo_odr_mHz, &odr_val); data = ST_LSM6DSX_SHIFT_VAL(odr_val, reg->mask); err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, data); if (err) return err; } return regmap_assign_bits(hw->regmap, settings->fifo_enable.addr, settings->fifo_enable.mask, enable); } int st_lsm6dsx_fusion_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) { struct st_lsm6dsx_hw *hw = sensor->hw; const struct st_lsm6dsx_reg *en_reg; int err; guard(mutex)(&hw->page_lock); en_reg = &hw->settings->fusion_settings.enable; err = st_lsm6dsx_fusion_page_enable(hw); if (err) return err; err = regmap_assign_bits(hw->regmap, en_reg->addr, en_reg->mask, enable); if (err) { st_lsm6dsx_fusion_page_disable(hw); return err; } return st_lsm6dsx_fusion_page_disable(hw); } int st_lsm6dsx_fusion_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable) { struct st_lsm6dsx_hw *hw = sensor->hw; int err; guard(mutex)(&hw->page_lock); err = st_lsm6dsx_fusion_page_enable(hw); if (err) return err; err = st_lsm6dsx_fusion_set_odr_locked(sensor, enable); if (err) { st_lsm6dsx_fusion_page_disable(hw); return err; } return st_lsm6dsx_fusion_page_disable(hw); } static int st_lsm6dsx_fusion_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) { struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: *val = sensor->hwfifo_odr_mHz / MILLI; *val2 = (sensor->hwfifo_odr_mHz % MILLI) * (MICRO / MILLI); return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } } static int st_lsm6dsx_fusion_write_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); const struct st_lsm6dsx_fusion_settings *settings; int err; settings = &sensor->hw->settings->fusion_settings; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: { u32 odr_mHz = val * MILLI + val2 * (MILLI / MICRO); u8 odr_val; /* check that the requested frequency is supported */ err = st_lsm6dsx_fusion_get_odr_val(settings, odr_mHz, &odr_val); if (err) return err; sensor->hwfifo_odr_mHz = odr_mHz; return 0; } default: return -EINVAL; } } static int st_lsm6dsx_fusion_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, const int **vals, int *type, int *length, long mask) { struct st_lsm6dsx_sensor *sensor = iio_priv(indio_dev); const struct st_lsm6dsx_fusion_settings *settings; settings = &sensor->hw->settings->fusion_settings; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: *vals = settings->odr_hz; *type = IIO_VAL_INT; *length = settings->odr_len; return IIO_AVAIL_LIST; default: return -EINVAL; } } static const struct iio_info st_lsm6dsx_fusion_info = { .read_raw = st_lsm6dsx_fusion_read_raw, .read_avail = st_lsm6dsx_fusion_read_avail, .write_raw = st_lsm6dsx_fusion_write_raw, .hwfifo_set_watermark = st_lsm6dsx_set_watermark, }; int st_lsm6dsx_fusion_probe(struct st_lsm6dsx_hw *hw, const char *name) { const struct st_lsm6dsx_fusion_settings *settings; struct st_lsm6dsx_sensor *sensor; struct iio_dev *iio_dev; int ret; iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor)); if (!iio_dev) return -ENOMEM; settings = &hw->settings->fusion_settings; sensor = iio_priv(iio_dev); sensor->id = ST_LSM6DSX_ID_FUSION; sensor->hw = hw; sensor->hwfifo_odr_mHz = settings->odr_hz[0] * MILLI; sensor->watermark = 1; iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->info = &st_lsm6dsx_fusion_info; iio_dev->channels = settings->chan; iio_dev->num_channels = settings->chan_len; ret = snprintf(sensor->name, sizeof(sensor->name), "%s_fusion", name); if (ret >= sizeof(sensor->name)) return -E2BIG; iio_dev->name = sensor->name; /* * Put the IIO device pointer in the iio_devs array so that the caller * can set up a buffer and register this IIO device. */ hw->iio_devs[ST_LSM6DSX_ID_FUSION] = iio_dev; return 0; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1