| /* ST Microelectronics STTS22H temperature sensor |
| * |
| * Copyright (c) 2024 STMicroelectronics |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| * |
| * Datasheet: |
| * https://www.st.com/resource/en/datasheet/stts22h.pdf |
| */ |
| |
| #define DT_DRV_COMPAT st_stts22h |
| |
| #include <zephyr/drivers/sensor.h> |
| #include <zephyr/kernel.h> |
| #include <zephyr/device.h> |
| #include <zephyr/init.h> |
| #include <zephyr/sys/byteorder.h> |
| #include <zephyr/sys/__assert.h> |
| #include <zephyr/logging/log.h> |
| |
| #include "stts22h.h" |
| |
| LOG_MODULE_REGISTER(STTS22H, CONFIG_SENSOR_LOG_LEVEL); |
| |
| static inline int stts22h_set_odr_raw(const struct device *dev, stts22h_odr_temp_t odr) |
| { |
| const struct stts22h_config *cfg = dev->config; |
| stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; |
| |
| return stts22h_temp_data_rate_set(ctx, odr); |
| } |
| |
| static int stts22h_sample_fetch(const struct device *dev, enum sensor_channel chan) |
| { |
| struct stts22h_data *data = dev->data; |
| const struct stts22h_config *cfg = dev->config; |
| stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; |
| int16_t raw_temp; |
| |
| if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) { |
| LOG_ERR("Invalid channel: %d", chan); |
| return -ENOTSUP; |
| } |
| |
| if (stts22h_temperature_raw_get(ctx, &raw_temp) < 0) { |
| LOG_ERR("Failed to read sample"); |
| return -EIO; |
| } |
| |
| data->sample_temp = raw_temp; |
| |
| return 0; |
| } |
| |
| static inline void stts22h_temp_convert(struct sensor_value *val, int16_t raw_val) |
| { |
| val->val1 = raw_val / 100; |
| val->val2 = ((int32_t)raw_val % 100) * 10000; |
| } |
| |
| static int stts22h_channel_get(const struct device *dev, |
| enum sensor_channel chan, |
| struct sensor_value *val) |
| { |
| struct stts22h_data *data = dev->data; |
| |
| if (chan != SENSOR_CHAN_AMBIENT_TEMP) { |
| LOG_ERR("Invalid channel: %d", chan); |
| return -ENOTSUP; |
| } |
| |
| stts22h_temp_convert(val, data->sample_temp); |
| |
| return 0; |
| } |
| |
| static const uint8_t stts22h_map[6] = {0, 1, 25, 50, 100, 200}; |
| |
| static int stts22h_odr_set(const struct device *dev, |
| const struct sensor_value *val) |
| { |
| int odr; |
| |
| for (odr = 0; odr < ARRAY_SIZE(stts22h_map); odr++) { |
| if (val->val1 <= stts22h_map[odr]) { |
| break; |
| } |
| } |
| |
| switch (odr) { |
| case 0: |
| return stts22h_set_odr_raw(dev, STTS22H_POWER_DOWN); |
| case 1: |
| return stts22h_set_odr_raw(dev, STTS22H_1Hz); |
| case 2: |
| return stts22h_set_odr_raw(dev, STTS22H_25Hz); |
| case 3: |
| return stts22h_set_odr_raw(dev, STTS22H_50Hz); |
| case 4: |
| return stts22h_set_odr_raw(dev, STTS22H_100Hz); |
| case 5: |
| return stts22h_set_odr_raw(dev, STTS22H_200Hz); |
| default: |
| LOG_ERR("bad frequency: %d (odr = %d)", val->val1, odr); |
| return -EINVAL; |
| } |
| } |
| |
| static int stts22h_attr_set(const struct device *dev, |
| enum sensor_channel chan, |
| enum sensor_attribute attr, |
| const struct sensor_value *val) |
| { |
| if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) { |
| LOG_ERR("Invalid channel: %d", chan); |
| return -ENOTSUP; |
| } |
| |
| switch (attr) { |
| case SENSOR_ATTR_SAMPLING_FREQUENCY: |
| return stts22h_odr_set(dev, val); |
| default: |
| LOG_ERR("Attribute %d not supported.", attr); |
| return -ENOTSUP; |
| } |
| |
| return 0; |
| } |
| |
| static const struct sensor_driver_api stts22h_api_funcs = { |
| .attr_set = stts22h_attr_set, |
| .sample_fetch = stts22h_sample_fetch, |
| .channel_get = stts22h_channel_get, |
| #if CONFIG_STTS22H_TRIGGER |
| .trigger_set = stts22h_trigger_set, |
| #endif |
| }; |
| |
| static int stts22h_init_chip(const struct device *dev) |
| { |
| const struct stts22h_config *cfg = dev->config; |
| stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; |
| uint8_t chip_id, odr; |
| |
| if (stts22h_dev_id_get(ctx, &chip_id) < 0) { |
| LOG_ERR("Failed reading chip id"); |
| return -EIO; |
| } |
| |
| LOG_INF("chip id 0x%02x", chip_id); |
| |
| if (stts22h_auto_increment_set(ctx, 1) < 0) { |
| LOG_ERR("Failed to set autoincr"); |
| return -EIO; |
| } |
| |
| /* set odr from DT */ |
| odr = cfg->odr; |
| LOG_INF("sensor odr is %d", odr); |
| if (stts22h_set_odr_raw(dev, odr) < 0) { |
| LOG_ERR("Failed to set sampling rate"); |
| return -EIO; |
| } |
| |
| return 0; |
| } |
| |
| static int stts22h_init(const struct device *dev) |
| { |
| struct stts22h_data *data = dev->data; |
| #ifdef CONFIG_STTS22H_TRIGGER |
| const struct stts22h_config *cfg = dev->config; |
| #endif |
| |
| LOG_INF("Initialize device %s", dev->name); |
| data->dev = dev; |
| |
| if (stts22h_init_chip(dev) < 0) { |
| LOG_ERR("Failed to initialize chip"); |
| return -EIO; |
| } |
| |
| #ifdef CONFIG_STTS22H_TRIGGER |
| if (cfg->int_gpio.port) { |
| if (stts22h_init_interrupt(dev) < 0) { |
| LOG_ERR("Failed to initialize interrupt."); |
| return -EIO; |
| } |
| } |
| #endif |
| |
| return 0; |
| } |
| |
| #define STTS22H_DEFINE(inst) \ |
| static struct stts22h_data stts22h_data_##inst; \ |
| \ |
| static const struct stts22h_config stts22h_config_##inst = { \ |
| STMEMSC_CTX_I2C(&stts22h_config_##inst.i2c), \ |
| .i2c = I2C_DT_SPEC_INST_GET(inst), \ |
| .temp_hi = DT_INST_PROP(inst, temperature_hi_threshold), \ |
| .temp_lo = DT_INST_PROP(inst, temperature_lo_threshold), \ |
| .odr = DT_INST_PROP(inst, sampling_rate), \ |
| IF_ENABLED(CONFIG_STTS22H_TRIGGER, \ |
| (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }),)) \ |
| }; \ |
| \ |
| SENSOR_DEVICE_DT_INST_DEFINE(inst, stts22h_init, NULL, \ |
| &stts22h_data_##inst, &stts22h_config_##inst, POST_KERNEL, \ |
| CONFIG_SENSOR_INIT_PRIORITY, &stts22h_api_funcs); \ |
| |
| DT_INST_FOREACH_STATUS_OKAY(STTS22H_DEFINE) |