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