1 /*
2  * Copyright (c) 2024 MASSDRIVER EI (massdriver.space)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT phosense_xbr818
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/i2c.h>
11 
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(XBR818, CONFIG_SENSOR_LOG_LEVEL);
14 
15 #include "xbr818.h"
16 #include <zephyr/drivers/sensor/xbr818.h>
17 
xbr818_enable_i2c(const struct device * dev)18 static int xbr818_enable_i2c(const struct device *dev)
19 {
20 	const struct xbr818_config *config = dev->config;
21 	int ret;
22 
23 	if (config->i2c_en.port) {
24 		ret = gpio_pin_set_dt(&config->i2c_en, 1);
25 		if (ret != 0) {
26 			LOG_ERR("%s: could not set i2c_en pin", dev->name);
27 		}
28 		k_usleep(10);
29 		return ret;
30 	}
31 	return 0;
32 }
33 
xbr818_disable_i2c(const struct device * dev)34 static int xbr818_disable_i2c(const struct device *dev)
35 {
36 	const struct xbr818_config *config = dev->config;
37 	int ret;
38 
39 	if (config->i2c_en.port) {
40 		ret = gpio_pin_set_dt(&config->i2c_en, 0);
41 		if (ret != 0) {
42 			LOG_ERR("%s: could not unset i2c_en pin", dev->name);
43 		}
44 		return ret;
45 	}
46 	return 0;
47 }
48 
xbr818_sample_fetch(const struct device * dev,enum sensor_channel chan)49 static int xbr818_sample_fetch(const struct device *dev, enum sensor_channel chan)
50 {
51 	const struct xbr818_config *config = dev->config;
52 	struct xbr818_data *data = dev->data;
53 	int ret;
54 
55 	if (chan != SENSOR_CHAN_PROX && chan != SENSOR_CHAN_ALL) {
56 		LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
57 		return -ENOTSUP;
58 	}
59 
60 	ret = gpio_pin_get_dt(&config->io_val);
61 	if (ret < 0) {
62 		return ret;
63 	}
64 	data->value = (ret == 1 ? true : false);
65 
66 	return 0;
67 }
68 
xbr818_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)69 static int xbr818_channel_get(const struct device *dev, enum sensor_channel chan,
70 			      struct sensor_value *val)
71 {
72 	struct xbr818_data *data = dev->data;
73 
74 	if (chan != SENSOR_CHAN_PROX) {
75 		LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
76 		return -ENOTSUP;
77 	}
78 
79 	val->val1 = (data->value ? 1 : 0);
80 	val->val2 = 0;
81 
82 	return 0;
83 }
84 
xbr818_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)85 static int xbr818_attr_set(const struct device *dev, enum sensor_channel chan,
86 			   enum sensor_attribute attr, const struct sensor_value *val)
87 {
88 	const struct xbr818_config *config = dev->config;
89 	int ret;
90 	uint8_t tmp[3];
91 	uint64_t tmpf;
92 
93 	if (chan != SENSOR_CHAN_PROX) {
94 		LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
95 		return -ENOTSUP;
96 	}
97 
98 	if (val->val1 < 0) {
99 		return -EINVAL;
100 	}
101 
102 	ret = xbr818_enable_i2c(dev);
103 	if (ret != 0) {
104 		return ret;
105 	}
106 
107 	if (attr == SENSOR_ATTR_LOWER_THRESH) {
108 		if (val->val1 > 0xFFFF || val->val1 < 0) {
109 			return -EINVAL;
110 		}
111 		tmp[0] = val->val1 & 0xFF;
112 		tmp[1] = (val->val1 & 0xFF00) >> 8;
113 		ret = i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_1, tmp, 2);
114 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_NOISE_FLOOR) {
115 		if (val->val1 > 0xFFFF || val->val1 < 0) {
116 			return -EINVAL;
117 		}
118 		tmp[0] = val->val1 & 0xFF;
119 		tmp[1] = (val->val1 & 0xFF00) >> 8;
120 		ret = i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_NOISE_1, tmp, 2);
121 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_DELAY_TIME) {
122 		if (val->val1 < 0 || val->val2 < 0) {
123 			return -EINVAL;
124 		}
125 		tmpf = (uint64_t)val->val1 * 1000000 + (uint64_t)val->val2;
126 		tmpf = (tmpf * SENSOR_XBR818_CLOCKRATE) / 1000000;
127 		if (tmpf > 0xFFFFFF) {
128 			return -EINVAL;
129 		}
130 		tmp[0] = tmpf & 0xFF;
131 		tmp[1] = (tmpf & 0xFF00) >> 8;
132 		tmp[2] = (tmpf & 0xFF0000) >> 16;
133 		ret = i2c_burst_write_dt(&config->i2c, XBR818_DELAY_TIME_1, tmp, 3);
134 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_LOCK_TIME) {
135 		if (val->val1 < 0 || val->val2 < 0) {
136 			return -EINVAL;
137 		}
138 		tmpf = (uint64_t)val->val1 * 1000000 + (uint64_t)val->val2;
139 		tmpf = (tmpf * SENSOR_XBR818_CLOCKRATE) / 1000000;
140 		if (tmpf > 0xFFFFFF) {
141 			return -EINVAL;
142 		}
143 		tmp[0] = tmpf & 0xFF;
144 		tmp[1] = (tmpf & 0xFF00) >> 8;
145 		tmp[2] = (tmpf & 0xFF0000) >> 16;
146 		ret = i2c_burst_write_dt(&config->i2c, XBR818_LOCK_TIME_1, tmp, 3);
147 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_RF_POWER) {
148 		if (val->val1 > 0x7 || val->val1 < 0) {
149 			return -EINVAL;
150 		}
151 		tmp[0] = val->val1 & 0x7;
152 		ret = i2c_reg_write_byte_dt(&config->i2c, XBR818_RF_POWER, tmp[0]);
153 	} else if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) {
154 		if (val->val1 > SENSOR_XBR818_CLOCKRATE || val->val1 <= 0) {
155 			return -EINVAL;
156 		}
157 		tmp[0] = SENSOR_XBR818_CLOCKRATE / val->val1;
158 		if (tmp[0] > 0xFF) {
159 			return -EINVAL;
160 		}
161 		ret = i2c_reg_write_byte_dt(&config->i2c, XBR818_SAMPLE_RATE_DIVIDER, tmp[0]);
162 	} else {
163 		ret = xbr818_disable_i2c(dev);
164 		if (ret != 0) {
165 			return ret;
166 		}
167 		return -ENODEV;
168 	}
169 
170 	if (ret != 0) {
171 		return ret;
172 	}
173 
174 	ret = xbr818_disable_i2c(dev);
175 
176 	return ret;
177 }
178 
xbr818_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)179 static int xbr818_attr_get(const struct device *dev, enum sensor_channel chan,
180 			   enum sensor_attribute attr, struct sensor_value *val)
181 {
182 	const struct xbr818_config *config = dev->config;
183 	int ret;
184 	uint8_t tmp[3];
185 	uint64_t tmpf;
186 
187 	if (chan != SENSOR_CHAN_PROX) {
188 		LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
189 		return -ENOTSUP;
190 	}
191 
192 	ret = xbr818_enable_i2c(dev);
193 	if (ret != 0) {
194 		return ret;
195 	}
196 
197 	if (attr == SENSOR_ATTR_LOWER_THRESH) {
198 		ret = i2c_burst_read_dt(&config->i2c, XBR818_THRESHOLD_1, tmp, 2);
199 		if (ret != 0) {
200 			return ret;
201 		}
202 		val->val1 = tmp[0] & 0xFF;
203 		val->val1 |= (uint32_t)tmp[1] << 8;
204 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_NOISE_FLOOR) {
205 		ret = i2c_burst_read_dt(&config->i2c, XBR818_THRESHOLD_NOISE_1, tmp, 2);
206 		if (ret != 0) {
207 			return ret;
208 		}
209 		val->val1 = tmp[0] & 0xFF;
210 		val->val1 |= (uint32_t)tmp[1] << 8;
211 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_DELAY_TIME) {
212 		ret = i2c_burst_read_dt(&config->i2c, XBR818_DELAY_TIME_1, tmp, 3);
213 		if (ret != 0) {
214 			return ret;
215 		}
216 		val->val1 = tmp[0] & 0xFF;
217 		val->val1 |= (uint32_t)tmp[1] << 8;
218 		val->val1 |= (uint32_t)tmp[2] << 16;
219 		tmpf = (uint64_t)val->val1 * 1000000;
220 		tmpf /= SENSOR_XBR818_CLOCKRATE;
221 		val->val1 = tmpf / 1000000;
222 		val->val2 = tmpf - val->val1 * 1000000;
223 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_LOCK_TIME) {
224 		ret = i2c_burst_read_dt(&config->i2c, XBR818_LOCK_TIME_1, tmp, 3);
225 		if (ret != 0) {
226 			return ret;
227 		}
228 		val->val1 = tmp[0] & 0xFF;
229 		val->val1 |= (uint32_t)tmp[1] << 8;
230 		val->val1 |= (uint32_t)tmp[2] << 16;
231 		tmpf = (uint64_t)val->val1 * 1000000;
232 		tmpf /= SENSOR_XBR818_CLOCKRATE;
233 		val->val1 = tmpf / 1000000;
234 		val->val2 = tmpf - val->val1 * 1000000;
235 	} else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_RF_POWER) {
236 		ret = i2c_reg_read_byte_dt(&config->i2c, XBR818_RF_POWER, tmp);
237 		if (ret != 0) {
238 			return ret;
239 		}
240 		val->val1 = *tmp & 0x7;
241 	} else if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) {
242 		ret = i2c_reg_read_byte_dt(&config->i2c, XBR818_SAMPLE_RATE_DIVIDER, tmp);
243 		if (ret != 0) {
244 			return ret;
245 		}
246 		val->val1 = SENSOR_XBR818_CLOCKRATE / *tmp;
247 	} else {
248 		ret = xbr818_disable_i2c(dev);
249 		if (ret != 0) {
250 			return ret;
251 		}
252 		return -ENODEV;
253 	}
254 
255 	ret = xbr818_disable_i2c(dev);
256 
257 	return ret;
258 }
259 
xbr818_work(struct k_work * work)260 static void xbr818_work(struct k_work *work)
261 {
262 	struct xbr818_data *data = CONTAINER_OF(work, struct xbr818_data, work);
263 
264 	if (likely(data->handler != NULL)) {
265 		data->handler(data->dev, data->trigger);
266 	}
267 }
268 
xbr818_gpio_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)269 static void xbr818_gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
270 {
271 	struct xbr818_data *data = CONTAINER_OF(cb, struct xbr818_data, gpio_cb);
272 
273 	k_work_submit(&data->work);
274 }
275 
xbr818_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)276 static int xbr818_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
277 			      sensor_trigger_handler_t handler)
278 {
279 	const struct xbr818_config *config = dev->config;
280 	struct xbr818_data *data = dev->data;
281 	int ret;
282 
283 	if (trig->chan != SENSOR_CHAN_PROX) {
284 		LOG_ERR("%s: requesting unsupported channel %i", dev->name, trig->chan);
285 		return -ENOTSUP;
286 	}
287 
288 	if (trig->type != SENSOR_TRIG_MOTION) {
289 		LOG_ERR("%s: requesting unsupported trigger %i", dev->name, trig->type);
290 		return -ENOTSUP;
291 	}
292 
293 	data->handler = handler;
294 	data->trigger = trig;
295 	ret = gpio_pin_interrupt_configure_dt(&config->io_val, GPIO_INT_EDGE_RISING);
296 	if (ret < 0) {
297 		return ret;
298 	}
299 
300 	if (handler) {
301 		ret = gpio_add_callback(config->io_val.port, &data->gpio_cb);
302 	} else {
303 		ret = gpio_remove_callback(config->io_val.port, &data->gpio_cb);
304 	}
305 
306 	return ret;
307 }
308 
xbr818_init_defaults(const struct device * dev)309 static int xbr818_init_defaults(const struct device *dev)
310 {
311 	const struct xbr818_config *config = dev->config;
312 	int ret = 0;
313 	uint8_t data[3];
314 
315 	ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_IO_ACTIVE_VALUE_REG, 0x03);
316 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_IO_ACTIVE_VALUE_REG");
317 	ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_RF_EN_SEL, 0x20);
318 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_RF_EN_SEL");
319 	ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_SAMPLE_RATE_DIVIDER, 0x20);
320 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_SAMPLE_RATE_DIVIDER");
321 	ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_RF_POWER, 0x45);
322 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_RF_POWER");
323 	ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_TIMER_CTRL, 0x21);
324 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_TIMER_CTRL");
325 
326 	data[0] = 0x5a;
327 	data[1] = 0x01;
328 	ret |= i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_1, data, 2);
329 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_THRESHOLD");
330 
331 	data[0] = 0x55;
332 	data[1] = 0x01;
333 	ret |= i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_NOISE_1, data, 2);
334 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_THRESHOLD_NOISE");
335 
336 	/* 0.1 seconds */
337 	data[0] = 0x80;
338 	data[1] = 0x0C;
339 	data[2] = 0x00;
340 	ret |= i2c_burst_write_dt(&config->i2c, XBR818_DELAY_TIME_1, data, 3);
341 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_DELAY_TIME");
342 
343 	/* 0.5 seconds */
344 	data[0] = 0x80;
345 	data[1] = 0x3E;
346 	data[2] = 0x00;
347 	ret |= i2c_burst_write_dt(&config->i2c, XBR818_LOCK_TIME_1, data, 3);
348 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_LOCK_TIME");
349 
350 	ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_PIN_SETTINGS, 0x0C);
351 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_PIN_SETTINGS");
352 
353 	ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_I2C_OUT, 0x1);
354 	__ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_I2C_OUT");
355 
356 	return ret;
357 }
358 
xbr818_init(const struct device * dev)359 static int xbr818_init(const struct device *dev)
360 {
361 	const struct xbr818_config *config = dev->config;
362 	struct xbr818_data *data = dev->data;
363 	int ret;
364 
365 	if (!i2c_is_ready_dt(&config->i2c)) {
366 		LOG_ERR("I2C device not ready");
367 		return -ENODEV;
368 	}
369 
370 	data->dev = dev;
371 	data->work.handler = xbr818_work;
372 
373 	ret = gpio_pin_configure_dt(&config->io_val, GPIO_INPUT);
374 	if (ret != 0) {
375 		LOG_ERR("%s: could not configure io_val(int) pin", dev->name);
376 		return ret;
377 	}
378 
379 	if (config->i2c_en.port) {
380 		ret = gpio_pin_configure_dt(&config->i2c_en, GPIO_OUTPUT);
381 		if (ret != 0) {
382 			LOG_ERR("%s: could not configure i2c_en pin", dev->name);
383 			return ret;
384 		}
385 	}
386 
387 	ret = xbr818_enable_i2c(dev);
388 	if (ret != 0) {
389 		return ret;
390 	}
391 
392 	ret = xbr818_init_defaults(dev);
393 	if (ret != 0) {
394 		LOG_ERR("%s: unable to configure", dev->name);
395 	}
396 
397 	ret = xbr818_disable_i2c(dev);
398 	if (ret != 0) {
399 		return ret;
400 	}
401 
402 	ret = gpio_pin_interrupt_configure_dt(&config->io_val, GPIO_INT_DISABLE);
403 	if (ret) {
404 		LOG_ERR("%s: failed to configure gpio interrupt: %d", dev->name, ret);
405 		return ret;
406 	}
407 
408 	gpio_init_callback(&data->gpio_cb, xbr818_gpio_callback, BIT(config->io_val.pin));
409 
410 	return ret;
411 }
412 
413 static DEVICE_API(sensor, xbr818_api) = {
414 	.sample_fetch = xbr818_sample_fetch,
415 	.channel_get = xbr818_channel_get,
416 	.attr_set = xbr818_attr_set,
417 	.attr_get = xbr818_attr_get,
418 	.trigger_set = xbr818_trigger_set,
419 };
420 
421 #define XBR818_INIT(inst)                                                                          \
422 	static const struct xbr818_config xbr818_##inst##_config = {                               \
423 		.i2c = I2C_DT_SPEC_INST_GET(inst),                                                 \
424 		.i2c_en = GPIO_DT_SPEC_GET_OR(DT_INST(inst, phosense_xbr818), i2c_en_gpios, {0}),  \
425 		.io_val = GPIO_DT_SPEC_GET(DT_INST(inst, phosense_xbr818), int_gpios),             \
426 	};                                                                                         \
427                                                                                                    \
428 	static struct xbr818_data xbr818_##inst##_data;                                            \
429                                                                                                    \
430 	SENSOR_DEVICE_DT_INST_DEFINE(inst, xbr818_init, NULL, &xbr818_##inst##_data,               \
431 				     &xbr818_##inst##_config, POST_KERNEL,                         \
432 				     CONFIG_SENSOR_INIT_PRIORITY, &xbr818_api);
433 
434 DT_INST_FOREACH_STATUS_OKAY(XBR818_INIT);
435