1 /* ST Microelectronics STTS22H temperature sensor
2 *
3 * Copyright (c) 2024 STMicroelectronics
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Datasheet:
8 * https://www.st.com/resource/en/datasheet/stts22h.pdf
9 */
10
11 #define DT_DRV_COMPAT st_stts22h
12
13 #include <zephyr/drivers/sensor.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/device.h>
16 #include <zephyr/init.h>
17 #include <zephyr/sys/byteorder.h>
18 #include <zephyr/sys/__assert.h>
19 #include <zephyr/logging/log.h>
20
21 #include "stts22h.h"
22
23 LOG_MODULE_REGISTER(STTS22H, CONFIG_SENSOR_LOG_LEVEL);
24
stts22h_set_odr_raw(const struct device * dev,stts22h_odr_temp_t odr)25 static inline int stts22h_set_odr_raw(const struct device *dev, stts22h_odr_temp_t odr)
26 {
27 const struct stts22h_config *cfg = dev->config;
28 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
29
30 return stts22h_temp_data_rate_set(ctx, odr);
31 }
32
stts22h_sample_fetch(const struct device * dev,enum sensor_channel chan)33 static int stts22h_sample_fetch(const struct device *dev, enum sensor_channel chan)
34 {
35 struct stts22h_data *data = dev->data;
36 const struct stts22h_config *cfg = dev->config;
37 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
38 int16_t raw_temp;
39
40 if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) {
41 LOG_ERR("Invalid channel: %d", chan);
42 return -ENOTSUP;
43 }
44
45 if (stts22h_temperature_raw_get(ctx, &raw_temp) < 0) {
46 LOG_ERR("Failed to read sample");
47 return -EIO;
48 }
49
50 data->sample_temp = raw_temp;
51
52 return 0;
53 }
54
stts22h_temp_convert(struct sensor_value * val,int16_t raw_val)55 static inline void stts22h_temp_convert(struct sensor_value *val, int16_t raw_val)
56 {
57 val->val1 = raw_val / 100;
58 val->val2 = ((int32_t)raw_val % 100) * 10000;
59 }
60
stts22h_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)61 static int stts22h_channel_get(const struct device *dev,
62 enum sensor_channel chan,
63 struct sensor_value *val)
64 {
65 struct stts22h_data *data = dev->data;
66
67 if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
68 LOG_ERR("Invalid channel: %d", chan);
69 return -ENOTSUP;
70 }
71
72 stts22h_temp_convert(val, data->sample_temp);
73
74 return 0;
75 }
76
77 static const uint8_t stts22h_map[6] = {0, 1, 25, 50, 100, 200};
78
stts22h_odr_set(const struct device * dev,const struct sensor_value * val)79 static int stts22h_odr_set(const struct device *dev,
80 const struct sensor_value *val)
81 {
82 int odr;
83
84 for (odr = 0; odr < ARRAY_SIZE(stts22h_map); odr++) {
85 if (val->val1 <= stts22h_map[odr]) {
86 break;
87 }
88 }
89
90 switch (odr) {
91 case 0:
92 return stts22h_set_odr_raw(dev, STTS22H_POWER_DOWN);
93 case 1:
94 return stts22h_set_odr_raw(dev, STTS22H_1Hz);
95 case 2:
96 return stts22h_set_odr_raw(dev, STTS22H_25Hz);
97 case 3:
98 return stts22h_set_odr_raw(dev, STTS22H_50Hz);
99 case 4:
100 return stts22h_set_odr_raw(dev, STTS22H_100Hz);
101 case 5:
102 return stts22h_set_odr_raw(dev, STTS22H_200Hz);
103 default:
104 LOG_ERR("bad frequency: %d (odr = %d)", val->val1, odr);
105 return -EINVAL;
106 }
107 }
108
stts22h_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)109 static int stts22h_attr_set(const struct device *dev,
110 enum sensor_channel chan,
111 enum sensor_attribute attr,
112 const struct sensor_value *val)
113 {
114 if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) {
115 LOG_ERR("Invalid channel: %d", chan);
116 return -ENOTSUP;
117 }
118
119 switch (attr) {
120 case SENSOR_ATTR_SAMPLING_FREQUENCY:
121 return stts22h_odr_set(dev, val);
122 default:
123 LOG_ERR("Attribute %d not supported.", attr);
124 return -ENOTSUP;
125 }
126
127 return 0;
128 }
129
130 static DEVICE_API(sensor, stts22h_api_funcs) = {
131 .attr_set = stts22h_attr_set,
132 .sample_fetch = stts22h_sample_fetch,
133 .channel_get = stts22h_channel_get,
134 #if CONFIG_STTS22H_TRIGGER
135 .trigger_set = stts22h_trigger_set,
136 #endif
137 };
138
stts22h_init_chip(const struct device * dev)139 static int stts22h_init_chip(const struct device *dev)
140 {
141 const struct stts22h_config *cfg = dev->config;
142 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
143 uint8_t chip_id, odr;
144
145 if (stts22h_dev_id_get(ctx, &chip_id) < 0) {
146 LOG_ERR("Failed reading chip id");
147 return -EIO;
148 }
149
150 LOG_INF("chip id 0x%02x", chip_id);
151
152 if (stts22h_auto_increment_set(ctx, 1) < 0) {
153 LOG_ERR("Failed to set autoincr");
154 return -EIO;
155 }
156
157 /* set odr from DT */
158 odr = cfg->odr;
159 LOG_INF("sensor odr is %d", odr);
160 if (stts22h_set_odr_raw(dev, odr) < 0) {
161 LOG_ERR("Failed to set sampling rate");
162 return -EIO;
163 }
164
165 return 0;
166 }
167
stts22h_init(const struct device * dev)168 static int stts22h_init(const struct device *dev)
169 {
170 struct stts22h_data *data = dev->data;
171 #ifdef CONFIG_STTS22H_TRIGGER
172 const struct stts22h_config *cfg = dev->config;
173 #endif
174
175 LOG_INF("Initialize device %s", dev->name);
176 data->dev = dev;
177
178 if (stts22h_init_chip(dev) < 0) {
179 LOG_ERR("Failed to initialize chip");
180 return -EIO;
181 }
182
183 #ifdef CONFIG_STTS22H_TRIGGER
184 if (cfg->int_gpio.port) {
185 if (stts22h_init_interrupt(dev) < 0) {
186 LOG_ERR("Failed to initialize interrupt.");
187 return -EIO;
188 }
189 }
190 #endif
191
192 return 0;
193 }
194
195 #define STTS22H_DEFINE(inst) \
196 static struct stts22h_data stts22h_data_##inst; \
197 \
198 static const struct stts22h_config stts22h_config_##inst = { \
199 STMEMSC_CTX_I2C(&stts22h_config_##inst.i2c), \
200 .i2c = I2C_DT_SPEC_INST_GET(inst), \
201 .temp_hi = DT_INST_PROP(inst, temperature_hi_threshold), \
202 .temp_lo = DT_INST_PROP(inst, temperature_lo_threshold), \
203 .odr = DT_INST_PROP(inst, sampling_rate), \
204 IF_ENABLED(CONFIG_STTS22H_TRIGGER, \
205 (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }),)) \
206 }; \
207 \
208 SENSOR_DEVICE_DT_INST_DEFINE(inst, stts22h_init, NULL, \
209 &stts22h_data_##inst, &stts22h_config_##inst, POST_KERNEL, \
210 CONFIG_SENSOR_INIT_PRIORITY, &stts22h_api_funcs); \
211
212 DT_INST_FOREACH_STATUS_OKAY(STTS22H_DEFINE)
213