1 /*
2 * Copyright (c) 2024 Gustavo Silva
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT sciosense_ens160
8
9 #include <zephyr/drivers/sensor/ens160.h>
10 #include <zephyr/init.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/pm/pm.h>
13 #include <zephyr/pm/device.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/__assert.h>
16
17 #include "ens160.h"
18
19 LOG_MODULE_REGISTER(ENS160, CONFIG_SENSOR_LOG_LEVEL);
20
ens160_set_temperature(const struct device * dev,const struct sensor_value * val)21 static int ens160_set_temperature(const struct device *dev, const struct sensor_value *val)
22 {
23 struct ens160_data *data = dev->data;
24 uint8_t buf[2];
25 int64_t temp;
26 int ret;
27
28 /* Recommended operation: -5 to 60 degrees Celsius */
29 if (!IN_RANGE(val->val1, -5, 60)) {
30 LOG_ERR("Invalid temperature value");
31 return -EINVAL;
32 }
33
34 /* Convert temperature from Celsius to Kelvin */
35 temp = sensor_value_to_micro(val) + 273150000U;
36 /* Temperature is stored in 64 * Kelvin */
37 temp *= 64;
38 sys_put_le16(DIV_ROUND_CLOSEST(temp, 1000000U), buf);
39
40 ret = data->tf->write_data(dev, ENS160_REG_TEMP_IN, buf, 2U);
41 if (ret < 0) {
42 LOG_ERR("Failed to write temperature");
43 return ret;
44 }
45
46 return 0;
47 }
48
ens160_set_humidity(const struct device * dev,const struct sensor_value * val)49 static int ens160_set_humidity(const struct device *dev, const struct sensor_value *val)
50 {
51 struct ens160_data *data = dev->data;
52 uint8_t buf[2];
53 uint64_t rh;
54 int ret;
55
56 /* Recommended operation: 20 to 80% RH */
57 if (!IN_RANGE(val->val1, 20, 80)) {
58 LOG_ERR("Invalid RH value");
59 return -EINVAL;
60 }
61
62 rh = sensor_value_to_micro(val);
63 /* RH value is stored in 512 * %RH */
64 rh *= 512;
65 sys_put_le16(DIV_ROUND_CLOSEST(rh, 1000000U), buf);
66
67 ret = data->tf->write_data(dev, ENS160_REG_RH_IN, buf, 2U);
68 if (ret < 0) {
69 LOG_ERR("Failed to write RH");
70 return ret;
71 }
72
73 return 0;
74 }
75
ens160_new_data(const struct device * dev)76 static bool ens160_new_data(const struct device *dev)
77 {
78 struct ens160_data *data = dev->data;
79 uint8_t status;
80 int ret;
81
82 ret = data->tf->read_reg(dev, ENS160_REG_DEVICE_STATUS, &status);
83 if (ret < 0) {
84 return ret;
85 }
86
87 return FIELD_GET(ENS160_STATUS_NEWDAT, status) != 0;
88 }
89
ens160_sample_fetch(const struct device * dev,enum sensor_channel chan)90 static int ens160_sample_fetch(const struct device *dev, enum sensor_channel chan)
91 {
92 struct ens160_data *data = dev->data;
93 uint16_t le16_buffer;
94 uint8_t buffer;
95 int ret;
96
97 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_CO2 ||
98 chan == SENSOR_CHAN_VOC ||
99 chan == (enum sensor_channel)SENSOR_CHAN_ENS160_AQI);
100
101 if (!IS_ENABLED(CONFIG_ENS160_TRIGGER)) {
102 WAIT_FOR(ens160_new_data(dev), ENS160_TIMEOUT_US, k_msleep(10));
103 }
104
105 ret = data->tf->read_data(dev, ENS160_REG_DATA_ECO2, (uint8_t *)&le16_buffer,
106 sizeof(le16_buffer));
107 if (ret < 0) {
108 LOG_ERR("Failed to fetch CO2");
109 return ret;
110 }
111
112 data->eco2 = sys_le16_to_cpu(le16_buffer);
113
114 ret = data->tf->read_data(dev, ENS160_REG_DATA_TVOC, (uint8_t *)&le16_buffer,
115 sizeof(le16_buffer));
116 if (ret < 0) {
117 LOG_ERR("Failed to fetch VOC");
118 return ret;
119 }
120
121 data->tvoc = sys_le16_to_cpu(le16_buffer);
122
123 ret = data->tf->read_reg(dev, ENS160_REG_DATA_AQI, &buffer);
124 if (ret < 0) {
125 LOG_ERR("Failed to fetch AQI");
126 return ret;
127 }
128
129 data->aqi = FIELD_GET(ENS160_DATA_AQI_UBA, buffer);
130
131 return 0;
132 }
133
ens160_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)134 static int ens160_channel_get(const struct device *dev, enum sensor_channel chan,
135 struct sensor_value *val)
136 {
137 struct ens160_data *data = dev->data;
138
139 switch (chan) {
140 case SENSOR_CHAN_CO2:
141 val->val1 = data->eco2;
142 val->val2 = 0;
143 break;
144 case SENSOR_CHAN_VOC:
145 val->val1 = data->tvoc;
146 val->val2 = 0;
147 break;
148 case SENSOR_CHAN_ENS160_AQI:
149 val->val1 = data->aqi;
150 val->val2 = 0;
151 break;
152 default:
153 return -ENOTSUP;
154 }
155
156 return 0;
157 }
158
ens160_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)159 static int ens160_attr_set(const struct device *dev, enum sensor_channel chan,
160 enum sensor_attribute attr, const struct sensor_value *val)
161 {
162 int ret = 0;
163
164 switch ((uint32_t)attr) {
165 case SENSOR_ATTR_ENS160_TEMP:
166 ret = ens160_set_temperature(dev, val);
167 break;
168 case SENSOR_ATTR_ENS160_RH:
169 ret = ens160_set_humidity(dev, val);
170 break;
171 default:
172 return -ENOTSUP;
173 }
174
175 return ret;
176 }
177
178 static const struct sensor_driver_api ens160_driver_api = {
179 .sample_fetch = ens160_sample_fetch,
180 .channel_get = ens160_channel_get,
181 .attr_set = ens160_attr_set,
182 #ifdef CONFIG_ENS160_TRIGGER
183 .trigger_set = ens160_trigger_set,
184 #endif
185 };
186
ens160_init(const struct device * dev)187 static int ens160_init(const struct device *dev)
188 {
189 const struct ens160_config *config = dev->config;
190 struct ens160_data *data = dev->data;
191 uint8_t fw_version[3];
192 uint16_t part_id;
193 uint8_t status;
194 int ret;
195
196 ret = config->bus_init(dev);
197 if (ret < 0) {
198 return ret;
199 }
200
201 ret = data->tf->write_reg(dev, ENS160_REG_OPMODE, ENS160_OPMODE_RESET);
202 if (ret < 0) {
203 LOG_ERR("Failed to reset the device");
204 return ret;
205 }
206
207 k_msleep(ENS160_BOOTING_TIME_MS);
208
209 ret = data->tf->read_data(dev, ENS160_REG_PART_ID, (uint8_t *)&part_id, sizeof(part_id));
210 if (ret < 0) {
211 LOG_ERR("Failed to read Part ID");
212 return -EIO;
213 }
214
215 if (sys_le16_to_cpu(part_id) != ENS160_PART_ID) {
216 LOG_ERR("Part ID is invalid. Expected: 0x%x; read: 0x%x", ENS160_PART_ID, part_id);
217 return -EIO;
218 }
219
220 ret = data->tf->write_reg(dev, ENS160_REG_OPMODE, ENS160_OPMODE_IDLE);
221 if (ret < 0) {
222 LOG_ERR("Failed to set operation mode");
223 return ret;
224 }
225
226 k_msleep(ENS160_BOOTING_TIME_MS);
227
228 ret = data->tf->write_reg(dev, ENS160_REG_COMMAND, ENS160_COMMAND_CLRGPR);
229 if (ret < 0) {
230 LOG_ERR("Failed to clear GPR registers");
231 return ret;
232 }
233
234 ret = data->tf->write_reg(dev, ENS160_REG_COMMAND, ENS160_COMMAND_GET_APPVER);
235 if (ret < 0) {
236 LOG_ERR("Failed to write GET_APPVER command");
237 return ret;
238 }
239
240 k_msleep(ENS160_BOOTING_TIME_MS);
241
242 ret = data->tf->read_data(dev, ENS160_REG_GPR_READ4, fw_version, sizeof(fw_version));
243 if (ret < 0) {
244 LOG_ERR("Failed to read firmware version");
245 return ret;
246 }
247 LOG_INF("Firmware version: %u.%u.%u", fw_version[2], fw_version[1], fw_version[0]);
248
249 #ifdef CONFIG_ENS160_TRIGGER
250 ret = ens160_init_interrupt(dev);
251 if (ret < 0) {
252 LOG_ERR("Failed to initialize interrupt");
253 return ret;
254 }
255 #endif /* CONFIG_ENS160_TRIGGER */
256
257 ret = data->tf->write_reg(dev, ENS160_REG_OPMODE, ENS160_OPMODE_STANDARD);
258 if (ret < 0) {
259 LOG_ERR("Failed to set operation mode");
260 return ret;
261 }
262
263 k_msleep(ENS160_BOOTING_TIME_MS);
264
265 ret = data->tf->read_reg(dev, ENS160_REG_DEVICE_STATUS, &status);
266 if (ret < 0) {
267 LOG_ERR("Failed to read device status");
268 return ret;
269 }
270
271 if (FIELD_GET(ENS160_STATUS_VALIDITY_FLAG, status) != ENS160_STATUS_NORMAL) {
272 LOG_ERR("Status 0x%02x is invalid", status);
273 return -EINVAL;
274 }
275
276 return 0;
277 }
278
279 #ifdef CONFIG_PM_DEVICE
ens160_pm_action(const struct device * dev,enum pm_device_action action)280 static int ens160_pm_action(const struct device *dev, enum pm_device_action action)
281 {
282 struct ens160_data *data = dev->data;
283 int ret = 0;
284
285 switch (action) {
286 case PM_DEVICE_ACTION_RESUME:
287 ret = data->tf->write_reg(dev, ENS160_REG_OPMODE, ENS160_OPMODE_IDLE);
288 k_msleep(ENS160_BOOTING_TIME_MS);
289 ret = data->tf->write_reg(dev, ENS160_REG_OPMODE, ENS160_OPMODE_STANDARD);
290 break;
291 case PM_DEVICE_ACTION_SUSPEND:
292 ret = data->tf->write_reg(dev, ENS160_REG_OPMODE, ENS160_OPMODE_DEEP_SLEEP);
293 break;
294 default:
295 return -ENOTSUP;
296 }
297
298 k_msleep(ENS160_BOOTING_TIME_MS);
299
300 return ret;
301 }
302 #endif
303
304 #define ENS160_SPI_OPERATION \
305 (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_TRANSFER_MSB)
306
307 #define ENS160_CONFIG_SPI(inst) \
308 .bus_init = &ens160_spi_init, \
309 .spi = SPI_DT_SPEC_INST_GET(inst, ENS160_SPI_OPERATION, 0),
310
311 #define ENS160_CONFIG_I2C(inst) \
312 .bus_init = &ens160_i2c_init, \
313 .i2c = I2C_DT_SPEC_INST_GET(inst),
314
315 #define ENS160_DEFINE(inst) \
316 static struct ens160_data ens160_data_##inst; \
317 static const struct ens160_config ens160_config_##inst = { \
318 IF_ENABLED(CONFIG_ENS160_TRIGGER, \
319 (.int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios),)) \
320 COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
321 (ENS160_CONFIG_SPI(inst)), \
322 (ENS160_CONFIG_I2C(inst))) \
323 }; \
324 \
325 PM_DEVICE_DT_INST_DEFINE(inst, ens160_pm_action); \
326 SENSOR_DEVICE_DT_INST_DEFINE(inst, ens160_init, PM_DEVICE_DT_INST_GET(inst), \
327 &ens160_data_##inst, &ens160_config_##inst, POST_KERNEL, \
328 CONFIG_SENSOR_INIT_PRIORITY, &ens160_driver_api);
329
330 DT_INST_FOREACH_STATUS_OKAY(ENS160_DEFINE)
331