123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- /* ST Microelectronics LSM6DSO 6-axis IMU sensor driver
- *
- * Copyright (c) 2019 STMicroelectronics
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Datasheet:
- * https://www.st.com/resource/en/datasheet/lsm6dso.pdf
- */
- #define DT_DRV_COMPAT st_lsm6dso
- #include <drivers/sensor.h>
- #include <kernel.h>
- #include <device.h>
- #include <init.h>
- #include <string.h>
- #include <sys/byteorder.h>
- #include <sys/__assert.h>
- #include <logging/log.h>
- #include "lsm6dso.h"
- LOG_MODULE_REGISTER(LSM6DSO, CONFIG_SENSOR_LOG_LEVEL);
- static const uint16_t lsm6dso_odr_map[] = {0, 12, 26, 52, 104, 208, 416, 833,
- 1660, 3330, 6660};
- #if defined(LSM6DSO_ACCEL_ODR_RUNTIME) || defined(LSM6DSO_GYRO_ODR_RUNTIME)
- static int lsm6dso_freq_to_odr_val(uint16_t freq)
- {
- size_t i;
- for (i = 0; i < ARRAY_SIZE(lsm6dso_odr_map); i++) {
- if (freq == lsm6dso_odr_map[i]) {
- return i;
- }
- }
- return -EINVAL;
- }
- #endif
- static int lsm6dso_odr_to_freq_val(uint16_t odr)
- {
- /* for valid index, return value from map */
- if (odr < ARRAY_SIZE(lsm6dso_odr_map)) {
- return lsm6dso_odr_map[odr];
- }
- /* invalid index, return last entry */
- return lsm6dso_odr_map[ARRAY_SIZE(lsm6dso_odr_map) - 1];
- }
- #ifdef LSM6DSO_ACCEL_FS_RUNTIME
- static const uint16_t lsm6dso_accel_fs_map[] = {2, 16, 4, 8};
- static const uint16_t lsm6dso_accel_fs_sens[] = {1, 8, 2, 4};
- static int lsm6dso_accel_range_to_fs_val(int32_t range)
- {
- size_t i;
- for (i = 0; i < ARRAY_SIZE(lsm6dso_accel_fs_map); i++) {
- if (range == lsm6dso_accel_fs_map[i]) {
- return i;
- }
- }
- return -EINVAL;
- }
- #endif
- #ifdef LSM6DSO_GYRO_FS_RUNTIME
- static const uint16_t lsm6dso_gyro_fs_map[] = {250, 500, 1000, 2000, 125};
- static const uint16_t lsm6dso_gyro_fs_sens[] = {2, 4, 8, 16, 1};
- static int lsm6dso_gyro_range_to_fs_val(int32_t range)
- {
- size_t i;
- for (i = 0; i < ARRAY_SIZE(lsm6dso_gyro_fs_map); i++) {
- if (range == lsm6dso_gyro_fs_map[i]) {
- return i;
- }
- }
- return -EINVAL;
- }
- #endif
- static inline int lsm6dso_reboot(const struct device *dev)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- if (lsm6dso_boot_set(ctx, 1) < 0) {
- return -EIO;
- }
- /* Wait sensor turn-on time as per datasheet */
- k_busy_wait(35 * USEC_PER_MSEC);
- return 0;
- }
- static int lsm6dso_accel_set_fs_raw(const struct device *dev, uint8_t fs)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- struct lsm6dso_data *data = dev->data;
- if (lsm6dso_xl_full_scale_set(ctx, fs) < 0) {
- return -EIO;
- }
- data->accel_fs = fs;
- return 0;
- }
- static int lsm6dso_accel_set_odr_raw(const struct device *dev, uint8_t odr)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- struct lsm6dso_data *data = dev->data;
- if (lsm6dso_xl_data_rate_set(ctx, odr) < 0) {
- return -EIO;
- }
- data->accel_freq = lsm6dso_odr_to_freq_val(odr);
- return 0;
- }
- static int lsm6dso_gyro_set_fs_raw(const struct device *dev, uint8_t fs)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- if (lsm6dso_gy_full_scale_set(ctx, fs) < 0) {
- return -EIO;
- }
- return 0;
- }
- static int lsm6dso_gyro_set_odr_raw(const struct device *dev, uint8_t odr)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- if (lsm6dso_gy_data_rate_set(ctx, odr) < 0) {
- return -EIO;
- }
- return 0;
- }
- #ifdef LSM6DSO_ACCEL_ODR_RUNTIME
- static int lsm6dso_accel_odr_set(const struct device *dev, uint16_t freq)
- {
- int odr;
- odr = lsm6dso_freq_to_odr_val(freq);
- if (odr < 0) {
- return odr;
- }
- if (lsm6dso_accel_set_odr_raw(dev, odr) < 0) {
- LOG_DBG("failed to set accelerometer sampling rate");
- return -EIO;
- }
- return 0;
- }
- #endif
- #ifdef LSM6DSO_ACCEL_FS_RUNTIME
- static int lsm6dso_accel_range_set(const struct device *dev, int32_t range)
- {
- int fs;
- struct lsm6dso_data *data = dev->data;
- fs = lsm6dso_accel_range_to_fs_val(range);
- if (fs < 0) {
- return fs;
- }
- if (lsm6dso_accel_set_fs_raw(dev, fs) < 0) {
- LOG_DBG("failed to set accelerometer full-scale");
- return -EIO;
- }
- data->acc_gain = (lsm6dso_accel_fs_sens[fs] * GAIN_UNIT_XL);
- return 0;
- }
- #endif
- static int lsm6dso_accel_config(const struct device *dev,
- enum sensor_channel chan,
- enum sensor_attribute attr,
- const struct sensor_value *val)
- {
- switch (attr) {
- #ifdef LSM6DSO_ACCEL_FS_RUNTIME
- case SENSOR_ATTR_FULL_SCALE:
- return lsm6dso_accel_range_set(dev, sensor_ms2_to_g(val));
- #endif
- #ifdef LSM6DSO_ACCEL_ODR_RUNTIME
- case SENSOR_ATTR_SAMPLING_FREQUENCY:
- return lsm6dso_accel_odr_set(dev, val->val1);
- #endif
- default:
- LOG_DBG("Accel attribute not supported.");
- return -ENOTSUP;
- }
- return 0;
- }
- #ifdef LSM6DSO_GYRO_ODR_RUNTIME
- static int lsm6dso_gyro_odr_set(const struct device *dev, uint16_t freq)
- {
- int odr;
- odr = lsm6dso_freq_to_odr_val(freq);
- if (odr < 0) {
- return odr;
- }
- if (lsm6dso_gyro_set_odr_raw(dev, odr) < 0) {
- LOG_DBG("failed to set gyroscope sampling rate");
- return -EIO;
- }
- return 0;
- }
- #endif
- #ifdef LSM6DSO_GYRO_FS_RUNTIME
- static int lsm6dso_gyro_range_set(const struct device *dev, int32_t range)
- {
- int fs;
- struct lsm6dso_data *data = dev->data;
- fs = lsm6dso_gyro_range_to_fs_val(range);
- if (fs < 0) {
- return fs;
- }
- if (lsm6dso_gyro_set_fs_raw(dev, fs) < 0) {
- LOG_DBG("failed to set gyroscope full-scale");
- return -EIO;
- }
- data->gyro_gain = (lsm6dso_gyro_fs_sens[fs] * GAIN_UNIT_G);
- return 0;
- }
- #endif
- static int lsm6dso_gyro_config(const struct device *dev,
- enum sensor_channel chan,
- enum sensor_attribute attr,
- const struct sensor_value *val)
- {
- switch (attr) {
- #ifdef LSM6DSO_GYRO_FS_RUNTIME
- case SENSOR_ATTR_FULL_SCALE:
- return lsm6dso_gyro_range_set(dev, sensor_rad_to_degrees(val));
- #endif
- #ifdef LSM6DSO_GYRO_ODR_RUNTIME
- case SENSOR_ATTR_SAMPLING_FREQUENCY:
- return lsm6dso_gyro_odr_set(dev, val->val1);
- #endif
- default:
- LOG_DBG("Gyro attribute not supported.");
- return -ENOTSUP;
- }
- return 0;
- }
- static int lsm6dso_attr_set(const struct device *dev,
- enum sensor_channel chan,
- enum sensor_attribute attr,
- const struct sensor_value *val)
- {
- #if defined(CONFIG_LSM6DSO_SENSORHUB)
- struct lsm6dso_data *data = dev->data;
- #endif /* CONFIG_LSM6DSO_SENSORHUB */
- switch (chan) {
- case SENSOR_CHAN_ACCEL_XYZ:
- return lsm6dso_accel_config(dev, chan, attr, val);
- case SENSOR_CHAN_GYRO_XYZ:
- return lsm6dso_gyro_config(dev, chan, attr, val);
- #if defined(CONFIG_LSM6DSO_SENSORHUB)
- case SENSOR_CHAN_MAGN_XYZ:
- case SENSOR_CHAN_PRESS:
- case SENSOR_CHAN_HUMIDITY:
- if (!data->shub_inited) {
- LOG_ERR("shub not inited.");
- return -ENOTSUP;
- }
- return lsm6dso_shub_config(dev, chan, attr, val);
- #endif /* CONFIG_LSM6DSO_SENSORHUB */
- default:
- LOG_WRN("attr_set() not supported on this channel.");
- return -ENOTSUP;
- }
- return 0;
- }
- static int lsm6dso_sample_fetch_accel(const struct device *dev)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- struct lsm6dso_data *data = dev->data;
- int16_t buf[3];
- if (lsm6dso_acceleration_raw_get(ctx, buf) < 0) {
- LOG_DBG("Failed to read sample");
- return -EIO;
- }
- data->acc[0] = sys_le16_to_cpu(buf[0]);
- data->acc[1] = sys_le16_to_cpu(buf[1]);
- data->acc[2] = sys_le16_to_cpu(buf[2]);
- return 0;
- }
- static int lsm6dso_sample_fetch_gyro(const struct device *dev)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- struct lsm6dso_data *data = dev->data;
- int16_t buf[3];
- if (lsm6dso_angular_rate_raw_get(ctx, buf) < 0) {
- LOG_DBG("Failed to read sample");
- return -EIO;
- }
- data->gyro[0] = sys_le16_to_cpu(buf[0]);
- data->gyro[1] = sys_le16_to_cpu(buf[1]);
- data->gyro[2] = sys_le16_to_cpu(buf[2]);
- return 0;
- }
- #if defined(CONFIG_LSM6DSO_ENABLE_TEMP)
- static int lsm6dso_sample_fetch_temp(const struct device *dev)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- struct lsm6dso_data *data = dev->data;
- int16_t buf;
- if (lsm6dso_temperature_raw_get(ctx, &buf) < 0) {
- LOG_DBG("Failed to read sample");
- return -EIO;
- }
- data->temp_sample = sys_le16_to_cpu(buf);
- return 0;
- }
- #endif
- #if defined(CONFIG_LSM6DSO_SENSORHUB)
- static int lsm6dso_sample_fetch_shub(const struct device *dev)
- {
- if (lsm6dso_shub_fetch_external_devs(dev) < 0) {
- LOG_DBG("failed to read ext shub devices");
- return -EIO;
- }
- return 0;
- }
- #endif /* CONFIG_LSM6DSO_SENSORHUB */
- static int lsm6dso_sample_fetch(const struct device *dev,
- enum sensor_channel chan)
- {
- #if defined(CONFIG_LSM6DSO_SENSORHUB)
- struct lsm6dso_data *data = dev->data;
- #endif /* CONFIG_LSM6DSO_SENSORHUB */
- switch (chan) {
- case SENSOR_CHAN_ACCEL_XYZ:
- lsm6dso_sample_fetch_accel(dev);
- break;
- case SENSOR_CHAN_GYRO_XYZ:
- lsm6dso_sample_fetch_gyro(dev);
- break;
- #if defined(CONFIG_LSM6DSO_ENABLE_TEMP)
- case SENSOR_CHAN_DIE_TEMP:
- lsm6dso_sample_fetch_temp(dev);
- break;
- #endif
- case SENSOR_CHAN_ALL:
- lsm6dso_sample_fetch_accel(dev);
- lsm6dso_sample_fetch_gyro(dev);
- #if defined(CONFIG_LSM6DSO_ENABLE_TEMP)
- lsm6dso_sample_fetch_temp(dev);
- #endif
- #if defined(CONFIG_LSM6DSO_SENSORHUB)
- if (data->shub_inited) {
- lsm6dso_sample_fetch_shub(dev);
- }
- #endif
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
- }
- static inline void lsm6dso_accel_convert(struct sensor_value *val, int raw_val,
- uint32_t sensitivity)
- {
- int64_t dval;
- /* Sensitivity is exposed in ug/LSB */
- /* Convert to m/s^2 */
- dval = (int64_t)(raw_val) * sensitivity * SENSOR_G_DOUBLE;
- val->val1 = (int32_t)(dval / 1000000);
- val->val2 = (int32_t)(dval % 1000000);
- }
- static inline int lsm6dso_accel_get_channel(enum sensor_channel chan,
- struct sensor_value *val,
- struct lsm6dso_data *data,
- uint32_t sensitivity)
- {
- uint8_t i;
- switch (chan) {
- case SENSOR_CHAN_ACCEL_X:
- lsm6dso_accel_convert(val, data->acc[0], sensitivity);
- break;
- case SENSOR_CHAN_ACCEL_Y:
- lsm6dso_accel_convert(val, data->acc[1], sensitivity);
- break;
- case SENSOR_CHAN_ACCEL_Z:
- lsm6dso_accel_convert(val, data->acc[2], sensitivity);
- break;
- case SENSOR_CHAN_ACCEL_XYZ:
- for (i = 0; i < 3; i++) {
- lsm6dso_accel_convert(val++, data->acc[i], sensitivity);
- }
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
- }
- static int lsm6dso_accel_channel_get(enum sensor_channel chan,
- struct sensor_value *val,
- struct lsm6dso_data *data)
- {
- return lsm6dso_accel_get_channel(chan, val, data, data->acc_gain);
- }
- static inline void lsm6dso_gyro_convert(struct sensor_value *val, int raw_val,
- uint32_t sensitivity)
- {
- int64_t dval;
- /* Sensitivity is exposed in udps/LSB */
- /* Convert to rad/s */
- dval = (int64_t)(raw_val) * sensitivity * SENSOR_DEG2RAD_DOUBLE;
- val->val1 = (int32_t)(dval / 1000000);
- val->val2 = (int32_t)(dval % 1000000);
- }
- static inline int lsm6dso_gyro_get_channel(enum sensor_channel chan,
- struct sensor_value *val,
- struct lsm6dso_data *data,
- uint32_t sensitivity)
- {
- uint8_t i;
- switch (chan) {
- case SENSOR_CHAN_GYRO_X:
- lsm6dso_gyro_convert(val, data->gyro[0], sensitivity);
- break;
- case SENSOR_CHAN_GYRO_Y:
- lsm6dso_gyro_convert(val, data->gyro[1], sensitivity);
- break;
- case SENSOR_CHAN_GYRO_Z:
- lsm6dso_gyro_convert(val, data->gyro[2], sensitivity);
- break;
- case SENSOR_CHAN_GYRO_XYZ:
- for (i = 0; i < 3; i++) {
- lsm6dso_gyro_convert(val++, data->gyro[i], sensitivity);
- }
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
- }
- static int lsm6dso_gyro_channel_get(enum sensor_channel chan,
- struct sensor_value *val,
- struct lsm6dso_data *data)
- {
- return lsm6dso_gyro_get_channel(chan, val, data,
- LSM6DSO_DEFAULT_GYRO_SENSITIVITY);
- }
- #if defined(CONFIG_LSM6DSO_ENABLE_TEMP)
- static void lsm6dso_gyro_channel_get_temp(struct sensor_value *val,
- struct lsm6dso_data *data)
- {
- /* val = temp_sample / 256 + 25 */
- val->val1 = data->temp_sample / 256 + 25;
- val->val2 = (data->temp_sample % 256) * (1000000 / 256);
- }
- #endif
- #if defined(CONFIG_LSM6DSO_SENSORHUB)
- static inline void lsm6dso_magn_convert(struct sensor_value *val, int raw_val,
- uint16_t sensitivity)
- {
- double dval;
- /* Sensitivity is exposed in mgauss/LSB */
- dval = (double)(raw_val * sensitivity);
- val->val1 = (int32_t)dval / 1000000;
- val->val2 = (int32_t)dval % 1000000;
- }
- static inline int lsm6dso_magn_get_channel(enum sensor_channel chan,
- struct sensor_value *val,
- struct lsm6dso_data *data)
- {
- int16_t sample[3];
- int idx;
- idx = lsm6dso_shub_get_idx(data->dev, SENSOR_CHAN_MAGN_XYZ);
- if (idx < 0) {
- LOG_DBG("external magn not supported");
- return -ENOTSUP;
- }
- sample[0] = sys_le16_to_cpu((int16_t)(data->ext_data[idx][0] |
- (data->ext_data[idx][1] << 8)));
- sample[1] = sys_le16_to_cpu((int16_t)(data->ext_data[idx][2] |
- (data->ext_data[idx][3] << 8)));
- sample[2] = sys_le16_to_cpu((int16_t)(data->ext_data[idx][4] |
- (data->ext_data[idx][5] << 8)));
- switch (chan) {
- case SENSOR_CHAN_MAGN_X:
- lsm6dso_magn_convert(val, sample[0], data->magn_gain);
- break;
- case SENSOR_CHAN_MAGN_Y:
- lsm6dso_magn_convert(val, sample[1], data->magn_gain);
- break;
- case SENSOR_CHAN_MAGN_Z:
- lsm6dso_magn_convert(val, sample[2], data->magn_gain);
- break;
- case SENSOR_CHAN_MAGN_XYZ:
- lsm6dso_magn_convert(val, sample[0], data->magn_gain);
- lsm6dso_magn_convert(val + 1, sample[1], data->magn_gain);
- lsm6dso_magn_convert(val + 2, sample[2], data->magn_gain);
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
- }
- static inline void lsm6dso_hum_convert(struct sensor_value *val,
- struct lsm6dso_data *data)
- {
- float rh;
- int16_t raw_val;
- struct hts221_data *ht = &data->hts221;
- int idx;
- idx = lsm6dso_shub_get_idx(data->dev, SENSOR_CHAN_HUMIDITY);
- if (idx < 0) {
- LOG_DBG("external press/temp not supported");
- return;
- }
- raw_val = sys_le16_to_cpu((int16_t)(data->ext_data[idx][0] |
- (data->ext_data[idx][1] << 8)));
- /* find relative humidty by linear interpolation */
- rh = (ht->y1 - ht->y0) * raw_val + ht->x1 * ht->y0 - ht->x0 * ht->y1;
- rh /= (ht->x1 - ht->x0);
- /* convert humidity to integer and fractional part */
- val->val1 = rh;
- val->val2 = rh * 1000000;
- }
- static inline void lsm6dso_press_convert(struct sensor_value *val,
- struct lsm6dso_data *data)
- {
- int32_t raw_val;
- int idx;
- idx = lsm6dso_shub_get_idx(data->dev, SENSOR_CHAN_PRESS);
- if (idx < 0) {
- LOG_DBG("external press/temp not supported");
- return;
- }
- raw_val = sys_le32_to_cpu((int32_t)(data->ext_data[idx][0] |
- (data->ext_data[idx][1] << 8) |
- (data->ext_data[idx][2] << 16)));
- /* Pressure sensitivity is 4096 LSB/hPa */
- /* Convert raw_val to val in kPa */
- val->val1 = (raw_val >> 12) / 10;
- val->val2 = (raw_val >> 12) % 10 * 100000 +
- (((int32_t)((raw_val) & 0x0FFF) * 100000L) >> 12);
- }
- static inline void lsm6dso_temp_convert(struct sensor_value *val,
- struct lsm6dso_data *data)
- {
- int16_t raw_val;
- int idx;
- idx = lsm6dso_shub_get_idx(data->dev, SENSOR_CHAN_PRESS);
- if (idx < 0) {
- LOG_DBG("external press/temp not supported");
- return;
- }
- raw_val = sys_le16_to_cpu((int16_t)(data->ext_data[idx][3] |
- (data->ext_data[idx][4] << 8)));
- /* Temperature sensitivity is 100 LSB/deg C */
- val->val1 = raw_val / 100;
- val->val2 = (int32_t)raw_val % 100 * (10000);
- }
- #endif
- static int lsm6dso_channel_get(const struct device *dev,
- enum sensor_channel chan,
- struct sensor_value *val)
- {
- struct lsm6dso_data *data = dev->data;
- switch (chan) {
- case SENSOR_CHAN_ACCEL_X:
- case SENSOR_CHAN_ACCEL_Y:
- case SENSOR_CHAN_ACCEL_Z:
- case SENSOR_CHAN_ACCEL_XYZ:
- lsm6dso_accel_channel_get(chan, val, data);
- break;
- case SENSOR_CHAN_GYRO_X:
- case SENSOR_CHAN_GYRO_Y:
- case SENSOR_CHAN_GYRO_Z:
- case SENSOR_CHAN_GYRO_XYZ:
- lsm6dso_gyro_channel_get(chan, val, data);
- break;
- #if defined(CONFIG_LSM6DSO_ENABLE_TEMP)
- case SENSOR_CHAN_DIE_TEMP:
- lsm6dso_gyro_channel_get_temp(val, data);
- break;
- #endif
- #if defined(CONFIG_LSM6DSO_SENSORHUB)
- case SENSOR_CHAN_MAGN_X:
- case SENSOR_CHAN_MAGN_Y:
- case SENSOR_CHAN_MAGN_Z:
- case SENSOR_CHAN_MAGN_XYZ:
- if (!data->shub_inited) {
- LOG_ERR("attr_set() shub not inited.");
- return -ENOTSUP;
- }
- lsm6dso_magn_get_channel(chan, val, data);
- break;
- case SENSOR_CHAN_HUMIDITY:
- if (!data->shub_inited) {
- LOG_ERR("attr_set() shub not inited.");
- return -ENOTSUP;
- }
- lsm6dso_hum_convert(val, data);
- break;
- case SENSOR_CHAN_PRESS:
- if (!data->shub_inited) {
- LOG_ERR("attr_set() shub not inited.");
- return -ENOTSUP;
- }
- lsm6dso_press_convert(val, data);
- break;
- case SENSOR_CHAN_AMBIENT_TEMP:
- if (!data->shub_inited) {
- LOG_ERR("attr_set() shub not inited.");
- return -ENOTSUP;
- }
- lsm6dso_temp_convert(val, data);
- break;
- #endif
- default:
- return -ENOTSUP;
- }
- return 0;
- }
- static const struct sensor_driver_api lsm6dso_driver_api = {
- .attr_set = lsm6dso_attr_set,
- #if CONFIG_LSM6DSO_TRIGGER
- .trigger_set = lsm6dso_trigger_set,
- #endif
- .sample_fetch = lsm6dso_sample_fetch,
- .channel_get = lsm6dso_channel_get,
- };
- static int lsm6dso_init_chip(const struct device *dev)
- {
- const struct lsm6dso_config *cfg = dev->config;
- stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
- struct lsm6dso_data *lsm6dso = dev->data;
- uint8_t chip_id;
- if (lsm6dso_device_id_get(ctx, &chip_id) < 0) {
- LOG_DBG("Failed reading chip id");
- return -EIO;
- }
- LOG_INF("chip id 0x%x", chip_id);
- if (chip_id != LSM6DSO_ID) {
- LOG_DBG("Invalid chip id 0x%x", chip_id);
- return -EIO;
- }
- /* reset device */
- if (lsm6dso_reset_set(ctx, 1) < 0) {
- return -EIO;
- }
- k_busy_wait(100);
- if (lsm6dso_accel_set_fs_raw(dev,
- LSM6DSO_DEFAULT_ACCEL_FULLSCALE) < 0) {
- LOG_DBG("failed to set accelerometer full-scale");
- return -EIO;
- }
- lsm6dso->acc_gain = LSM6DSO_DEFAULT_ACCEL_SENSITIVITY;
- lsm6dso->accel_freq = lsm6dso_odr_to_freq_val(CONFIG_LSM6DSO_ACCEL_ODR);
- if (lsm6dso_accel_set_odr_raw(dev, CONFIG_LSM6DSO_ACCEL_ODR) < 0) {
- LOG_DBG("failed to set accelerometer sampling rate");
- return -EIO;
- }
- if (lsm6dso_gyro_set_fs_raw(dev, LSM6DSO_DEFAULT_GYRO_FULLSCALE) < 0) {
- LOG_DBG("failed to set gyroscope full-scale");
- return -EIO;
- }
- lsm6dso->gyro_gain = LSM6DSO_DEFAULT_GYRO_SENSITIVITY;
- lsm6dso->gyro_freq = lsm6dso_odr_to_freq_val(CONFIG_LSM6DSO_GYRO_ODR);
- if (lsm6dso_gyro_set_odr_raw(dev, CONFIG_LSM6DSO_GYRO_ODR) < 0) {
- LOG_DBG("failed to set gyroscope sampling rate");
- return -EIO;
- }
- /* Set FIFO bypass mode */
- if (lsm6dso_fifo_mode_set(ctx, LSM6DSO_BYPASS_MODE) < 0) {
- LOG_DBG("failed to set FIFO mode");
- return -EIO;
- }
- if (lsm6dso_block_data_update_set(ctx, 1) < 0) {
- LOG_DBG("failed to set BDU mode");
- return -EIO;
- }
- return 0;
- }
- static int lsm6dso_init(const struct device *dev)
- {
- #ifdef CONFIG_LSM6DSO_TRIGGER
- const struct lsm6dso_config *cfg = dev->config;
- #endif
- struct lsm6dso_data *data = dev->data;
- LOG_INF("Initialize device %s", dev->name);
- data->dev = dev;
- #ifdef CONFIG_LSM6DSO_TRIGGER
- if (cfg->trig_enabled) {
- if (lsm6dso_init_interrupt(dev) < 0) {
- LOG_ERR("Failed to initialize interrupt.");
- return -EIO;
- }
- }
- #endif
- if (lsm6dso_init_chip(dev) < 0) {
- LOG_DBG("failed to initialize chip");
- return -EIO;
- }
- #ifdef CONFIG_LSM6DSO_SENSORHUB
- data->shub_inited = true;
- if (lsm6dso_shub_init(dev) < 0) {
- LOG_INF("shub: no external chips found");
- data->shub_inited = false;
- }
- #endif
- return 0;
- }
- #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
- #warning "LSM6DSO driver enabled without any devices"
- #endif
- /*
- * Device creation macro, shared by LSM6DSO_DEFINE_SPI() and
- * LSM6DSO_DEFINE_I2C().
- */
- #define LSM6DSO_DEVICE_INIT(inst) \
- DEVICE_DT_INST_DEFINE(inst, \
- lsm6dso_init, \
- NULL, \
- &lsm6dso_data_##inst, \
- &lsm6dso_config_##inst, \
- POST_KERNEL, \
- CONFIG_SENSOR_INIT_PRIORITY, \
- &lsm6dso_driver_api);
- /*
- * Instantiation macros used when a device is on a SPI bus.
- */
- #ifdef CONFIG_LSM6DSO_TRIGGER
- #define LSM6DSO_CFG_IRQ(inst) \
- .trig_enabled = true, \
- .gpio_drdy = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), \
- .int_pin = DT_INST_PROP(inst, int_pin)
- #else
- #define LSM6DSO_CFG_IRQ(inst)
- #endif /* CONFIG_LSM6DSO_TRIGGER */
- #define LSM6DSO_SPI_OP (SPI_WORD_SET(8) | \
- SPI_OP_MODE_MASTER | \
- SPI_LINES_SINGLE | \
- SPI_MODE_CPOL | \
- SPI_MODE_CPHA) \
- #define LSM6DSO_CONFIG_SPI(inst) \
- { \
- .ctx = { \
- .read_reg = \
- (stmdev_read_ptr) stmemsc_spi_read, \
- .write_reg = \
- (stmdev_write_ptr) stmemsc_spi_write, \
- .handle = \
- (void *)&lsm6dso_config_##inst.stmemsc_cfg, \
- }, \
- .stmemsc_cfg.spi = { \
- .bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \
- .spi_cfg = SPI_CONFIG_DT_INST(inst, \
- LSM6DSO_SPI_OP, \
- 0), \
- }, \
- COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \
- (LSM6DSO_CFG_IRQ(inst)), ()) \
- }
- /*
- * Instantiation macros used when a device is on an I2C bus.
- */
- #define LSM6DSO_CONFIG_I2C(inst) \
- { \
- .ctx = { \
- .read_reg = \
- (stmdev_read_ptr) stmemsc_i2c_read, \
- .write_reg = \
- (stmdev_write_ptr) stmemsc_i2c_write, \
- .handle = \
- (void *)&lsm6dso_config_##inst.stmemsc_cfg, \
- }, \
- .stmemsc_cfg.i2c = { \
- .bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \
- .i2c_slv_addr = DT_INST_REG_ADDR(inst), \
- }, \
- COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \
- (LSM6DSO_CFG_IRQ(inst)), ()) \
- }
- /*
- * Main instantiation macro. Use of COND_CODE_1() selects the right
- * bus-specific macro at preprocessor time.
- */
- #define LSM6DSO_DEFINE(inst) \
- static struct lsm6dso_data lsm6dso_data_##inst; \
- static const struct lsm6dso_config lsm6dso_config_##inst = \
- COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
- (LSM6DSO_CONFIG_SPI(inst)), \
- (LSM6DSO_CONFIG_I2C(inst))); \
- LSM6DSO_DEVICE_INIT(inst)
- DT_INST_FOREACH_STATUS_OKAY(LSM6DSO_DEFINE)
|