1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright (c) 2018 Phytec Messtechnik GmbH
4  *
5  *SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT avago_apds9960
9 
10 /* @file
11  * @brief driver for APDS9960 ALS/RGB/gesture/proximity sensor
12  */
13 
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/sensor.h>
16 #include <zephyr/drivers/i2c.h>
17 #include <zephyr/pm/device.h>
18 #include <zephyr/sys/__assert.h>
19 #include <zephyr/sys/byteorder.h>
20 #include <zephyr/init.h>
21 #include <zephyr/kernel.h>
22 #include <string.h>
23 #include <zephyr/logging/log.h>
24 
25 #include "apds9960.h"
26 
27 LOG_MODULE_REGISTER(APDS9960, CONFIG_SENSOR_LOG_LEVEL);
28 
apds9960_handle_cb(struct apds9960_data * drv_data)29 static void apds9960_handle_cb(struct apds9960_data *drv_data)
30 {
31 	apds9960_setup_int(drv_data->dev->config, false);
32 
33 #ifdef CONFIG_APDS9960_TRIGGER
34 	k_work_submit(&drv_data->work);
35 #else
36 	k_sem_give(&drv_data->data_sem);
37 #endif
38 }
39 
apds9960_gpio_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)40 static void apds9960_gpio_callback(const struct device *dev,
41 				   struct gpio_callback *cb, uint32_t pins)
42 {
43 	struct apds9960_data *drv_data =
44 		CONTAINER_OF(cb, struct apds9960_data, gpio_cb);
45 
46 	apds9960_handle_cb(drv_data);
47 }
48 
apds9960_sample_fetch(const struct device * dev,enum sensor_channel chan)49 static int apds9960_sample_fetch(const struct device *dev,
50 				 enum sensor_channel chan)
51 {
52 	const struct apds9960_config *config = dev->config;
53 	struct apds9960_data *data = dev->data;
54 	uint8_t tmp;
55 
56 	if (chan != SENSOR_CHAN_ALL) {
57 		LOG_ERR("Unsupported sensor channel");
58 		return -ENOTSUP;
59 	}
60 
61 #ifndef CONFIG_APDS9960_TRIGGER
62 	apds9960_setup_int(config, true);
63 
64 #ifdef CONFIG_APDS9960_ENABLE_ALS
65 	tmp = APDS9960_ENABLE_PON | APDS9960_ENABLE_AIEN;
66 #else
67 	tmp = APDS9960_ENABLE_PON | APDS9960_ENABLE_PIEN;
68 #endif
69 	if (i2c_reg_update_byte_dt(&config->i2c,
70 				APDS9960_ENABLE_REG, tmp, tmp)) {
71 		LOG_ERR("Power on bit not set.");
72 		return -EIO;
73 	}
74 
75 	k_sem_take(&data->data_sem, K_FOREVER);
76 #endif
77 
78 	if (i2c_reg_read_byte_dt(&config->i2c,
79 			      APDS9960_STATUS_REG, &tmp)) {
80 		return -EIO;
81 	}
82 
83 	LOG_DBG("status: 0x%x", tmp);
84 	if (tmp & APDS9960_STATUS_PINT) {
85 		if (i2c_reg_read_byte_dt(&config->i2c,
86 				      APDS9960_PDATA_REG, &data->pdata)) {
87 			return -EIO;
88 		}
89 	}
90 
91 	if (tmp & APDS9960_STATUS_AINT) {
92 		if (i2c_burst_read_dt(&config->i2c,
93 				   APDS9960_CDATAL_REG,
94 				   (uint8_t *)&data->sample_crgb,
95 				   sizeof(data->sample_crgb))) {
96 			return -EIO;
97 		}
98 
99 	}
100 
101 #ifndef CONFIG_APDS9960_TRIGGER
102 	if (i2c_reg_update_byte_dt(&config->i2c,
103 				APDS9960_ENABLE_REG,
104 				APDS9960_ENABLE_PON,
105 				0)) {
106 		return -EIO;
107 	}
108 #endif
109 
110 	if (i2c_reg_write_byte_dt(&config->i2c,
111 			       APDS9960_AICLEAR_REG, 0)) {
112 		return -EIO;
113 	}
114 
115 	return 0;
116 }
117 
apds9960_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)118 static int apds9960_channel_get(const struct device *dev,
119 				enum sensor_channel chan,
120 				struct sensor_value *val)
121 {
122 	struct apds9960_data *data = dev->data;
123 
124 	switch (chan) {
125 #ifdef CONFIG_APDS9960_ENABLE_ALS
126 	case SENSOR_CHAN_LIGHT:
127 		val->val1 = sys_le16_to_cpu(data->sample_crgb[0]);
128 		val->val2 = 0;
129 		break;
130 	case SENSOR_CHAN_RED:
131 		val->val1 = sys_le16_to_cpu(data->sample_crgb[1]);
132 		val->val2 = 0;
133 		break;
134 	case SENSOR_CHAN_GREEN:
135 		val->val1 = sys_le16_to_cpu(data->sample_crgb[2]);
136 		val->val2 = 0;
137 		break;
138 	case SENSOR_CHAN_BLUE:
139 		val->val1 = sys_le16_to_cpu(data->sample_crgb[3]);
140 		val->val2 = 0;
141 		break;
142 #endif
143 	case SENSOR_CHAN_PROX:
144 		val->val1 = data->pdata;
145 		val->val2 = 0;
146 		break;
147 	default:
148 		return -ENOTSUP;
149 	}
150 
151 	return 0;
152 }
153 
apds9960_proxy_setup(const struct device * dev)154 static int apds9960_proxy_setup(const struct device *dev)
155 {
156 	const struct apds9960_config *config = dev->config;
157 
158 	if (i2c_reg_write_byte_dt(&config->i2c,
159 			       APDS9960_POFFSET_UR_REG,
160 			       APDS9960_DEFAULT_POFFSET_UR)) {
161 		LOG_ERR("Default offset UR not set ");
162 		return -EIO;
163 	}
164 
165 	if (i2c_reg_write_byte_dt(&config->i2c,
166 			       APDS9960_POFFSET_DL_REG,
167 			       APDS9960_DEFAULT_POFFSET_DL)) {
168 		LOG_ERR("Default offset DL not set ");
169 		return -EIO;
170 	}
171 
172 	if (i2c_reg_write_byte_dt(&config->i2c,
173 			       APDS9960_PPULSE_REG,
174 			       config->ppcount)) {
175 		LOG_ERR("Default pulse count not set ");
176 		return -EIO;
177 	}
178 
179 	if (i2c_reg_update_byte_dt(&config->i2c,
180 				APDS9960_CONTROL_REG,
181 				APDS9960_CONTROL_LDRIVE,
182 				APDS9960_DEFAULT_LDRIVE)) {
183 		LOG_ERR("LED Drive Strength not set");
184 		return -EIO;
185 	}
186 
187 	if (i2c_reg_update_byte_dt(&config->i2c,
188 				APDS9960_CONFIG2_REG,
189 				APDS9960_PLED_BOOST_300,
190 				config->pled_boost)) {
191 		LOG_ERR("LED Drive Strength not set");
192 		return -EIO;
193 	}
194 
195 	if (i2c_reg_update_byte_dt(&config->i2c,
196 				APDS9960_CONTROL_REG, APDS9960_CONTROL_PGAIN,
197 				(config->pgain & APDS9960_PGAIN_8X))) {
198 		LOG_ERR("Gain is not set");
199 		return -EIO;
200 	}
201 
202 	if (i2c_reg_write_byte_dt(&config->i2c,
203 			       APDS9960_PILT_REG, APDS9960_DEFAULT_PILT)) {
204 		LOG_ERR("Low threshold not set");
205 		return -EIO;
206 	}
207 
208 	if (i2c_reg_write_byte_dt(&config->i2c,
209 			       APDS9960_PIHT_REG, APDS9960_DEFAULT_PIHT)) {
210 		LOG_ERR("High threshold not set");
211 		return -EIO;
212 	}
213 
214 	if (i2c_reg_update_byte_dt(&config->i2c,
215 				APDS9960_ENABLE_REG, APDS9960_ENABLE_PEN,
216 				APDS9960_ENABLE_PEN)) {
217 		LOG_ERR("Proximity mode is not enabled");
218 		return -EIO;
219 	}
220 
221 	return 0;
222 }
223 
224 #ifdef CONFIG_APDS9960_ENABLE_ALS
apds9960_ambient_setup(const struct device * dev)225 static int apds9960_ambient_setup(const struct device *dev)
226 {
227 	const struct apds9960_config *config = dev->config;
228 	uint16_t th;
229 
230 	/* ADC value */
231 	if (i2c_reg_write_byte_dt(&config->i2c,
232 			       APDS9960_ATIME_REG, APDS9960_DEFAULT_ATIME)) {
233 		LOG_ERR("Default integration time not set for ADC");
234 		return -EIO;
235 	}
236 
237 	/* ALS Gain */
238 	if (i2c_reg_update_byte_dt(&config->i2c,
239 				APDS9960_CONTROL_REG,
240 				APDS9960_CONTROL_AGAIN,
241 				(config->again & APDS9960_AGAIN_64X))) {
242 		LOG_ERR("Ambient Gain is not set");
243 		return -EIO;
244 	}
245 
246 	th = sys_cpu_to_le16(APDS9960_DEFAULT_AILT);
247 	if (i2c_burst_write_dt(&config->i2c,
248 			    APDS9960_INT_AILTL_REG,
249 			    (uint8_t *)&th, sizeof(th))) {
250 		LOG_ERR("ALS low threshold not set");
251 		return -EIO;
252 	}
253 
254 	th = sys_cpu_to_le16(APDS9960_DEFAULT_AIHT);
255 	if (i2c_burst_write_dt(&config->i2c,
256 			    APDS9960_INT_AIHTL_REG,
257 			    (uint8_t *)&th, sizeof(th))) {
258 		LOG_ERR("ALS low threshold not set");
259 		return -EIO;
260 	}
261 
262 	/* Enable ALS */
263 	if (i2c_reg_update_byte_dt(&config->i2c,
264 				APDS9960_ENABLE_REG, APDS9960_ENABLE_AEN,
265 				APDS9960_ENABLE_AEN)) {
266 		LOG_ERR("ALS is not enabled");
267 		return -EIO;
268 	}
269 
270 	return 0;
271 }
272 #endif
273 
apds9960_sensor_setup(const struct device * dev)274 static int apds9960_sensor_setup(const struct device *dev)
275 {
276 	const struct apds9960_config *config = dev->config;
277 	uint8_t chip_id;
278 
279 	if (i2c_reg_read_byte_dt(&config->i2c,
280 			      APDS9960_ID_REG, &chip_id)) {
281 		LOG_ERR("Failed reading chip id");
282 		return -EIO;
283 	}
284 
285 	if (!((chip_id == APDS9960_ID_1) || (chip_id == APDS9960_ID_2))) {
286 		LOG_ERR("Invalid chip id 0x%x", chip_id);
287 		return -EIO;
288 	}
289 
290 	/* Disable all functions and interrupts */
291 	if (i2c_reg_write_byte_dt(&config->i2c,
292 			       APDS9960_ENABLE_REG, 0)) {
293 		LOG_ERR("ENABLE register is not cleared");
294 		return -EIO;
295 	}
296 
297 	if (i2c_reg_write_byte_dt(&config->i2c,
298 			       APDS9960_AICLEAR_REG, 0)) {
299 		return -EIO;
300 	}
301 
302 	/* Disable gesture interrupt */
303 	if (i2c_reg_write_byte_dt(&config->i2c,
304 			       APDS9960_GCONFIG4_REG, 0)) {
305 		LOG_ERR("GCONFIG4 register is not cleared");
306 		return -EIO;
307 	}
308 
309 	if (i2c_reg_write_byte_dt(&config->i2c,
310 			       APDS9960_WTIME_REG, APDS9960_DEFAULT_WTIME)) {
311 		LOG_ERR("Default wait time not set");
312 		return -EIO;
313 	}
314 
315 	if (i2c_reg_write_byte_dt(&config->i2c,
316 			       APDS9960_CONFIG1_REG,
317 			       APDS9960_DEFAULT_CONFIG1)) {
318 		LOG_ERR("Default WLONG not set");
319 		return -EIO;
320 	}
321 
322 	if (i2c_reg_write_byte_dt(&config->i2c,
323 			       APDS9960_CONFIG2_REG,
324 			       APDS9960_DEFAULT_CONFIG2)) {
325 		LOG_ERR("Configuration Register Two not set");
326 		return -EIO;
327 	}
328 
329 	if (i2c_reg_write_byte_dt(&config->i2c,
330 			       APDS9960_CONFIG3_REG,
331 			       APDS9960_DEFAULT_CONFIG3)) {
332 		LOG_ERR("Configuration Register Three not set");
333 		return -EIO;
334 	}
335 
336 	if (i2c_reg_write_byte_dt(&config->i2c,
337 			       APDS9960_PERS_REG,
338 			       APDS9960_DEFAULT_PERS)) {
339 		LOG_ERR("Interrupt persistence not set");
340 		return -EIO;
341 	}
342 
343 	if (apds9960_proxy_setup(dev)) {
344 		LOG_ERR("Failed to setup proximity functionality");
345 		return -EIO;
346 	}
347 
348 #ifdef CONFIG_APDS9960_ENABLE_ALS
349 	if (apds9960_ambient_setup(dev)) {
350 		LOG_ERR("Failed to setup ambient light functionality");
351 		return -EIO;
352 	}
353 #endif
354 
355 	return 0;
356 }
357 
apds9960_init_interrupt(const struct device * dev)358 static int apds9960_init_interrupt(const struct device *dev)
359 {
360 	const struct apds9960_config *config = dev->config;
361 	struct apds9960_data *drv_data = dev->data;
362 
363 	if (!gpio_is_ready_dt(&config->int_gpio)) {
364 		LOG_ERR("%s: device %s is not ready", dev->name,
365 			config->int_gpio.port->name);
366 		return -ENODEV;
367 	}
368 
369 	gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT | config->int_gpio.dt_flags);
370 
371 	gpio_init_callback(&drv_data->gpio_cb,
372 			   apds9960_gpio_callback,
373 			   BIT(config->int_gpio.pin));
374 
375 	if (gpio_add_callback(config->int_gpio.port, &drv_data->gpio_cb) < 0) {
376 		LOG_DBG("Failed to set gpio callback!");
377 		return -EIO;
378 	}
379 
380 	drv_data->dev = dev;
381 
382 #ifdef CONFIG_APDS9960_TRIGGER
383 	drv_data->work.handler = apds9960_work_cb;
384 	if (i2c_reg_update_byte_dt(&config->i2c,
385 				APDS9960_ENABLE_REG,
386 				APDS9960_ENABLE_PON,
387 				APDS9960_ENABLE_PON)) {
388 		LOG_ERR("Power on bit not set.");
389 		return -EIO;
390 	}
391 
392 #else
393 	k_sem_init(&drv_data->data_sem, 0, K_SEM_MAX_LIMIT);
394 #endif
395 	apds9960_setup_int(config, true);
396 
397 	if (gpio_pin_get_dt(&config->int_gpio) > 0) {
398 		apds9960_handle_cb(drv_data);
399 	}
400 
401 	return 0;
402 }
403 
404 #ifdef CONFIG_PM_DEVICE
apds9960_pm_action(const struct device * dev,enum pm_device_action action)405 static int apds9960_pm_action(const struct device *dev,
406 			      enum pm_device_action action)
407 {
408 	const struct apds9960_config *config = dev->config;
409 	int ret = 0;
410 
411 	switch (action) {
412 	case PM_DEVICE_ACTION_RESUME:
413 		if (i2c_reg_update_byte_dt(&config->i2c,
414 					APDS9960_ENABLE_REG,
415 					APDS9960_ENABLE_PON,
416 					APDS9960_ENABLE_PON)) {
417 			ret = -EIO;
418 		}
419 		break;
420 	case PM_DEVICE_ACTION_SUSPEND:
421 		if (i2c_reg_update_byte_dt(&config->i2c,
422 					APDS9960_ENABLE_REG,
423 					APDS9960_ENABLE_PON, 0)) {
424 			ret = -EIO;
425 		}
426 
427 		if (i2c_reg_write_byte_dt(&config->i2c,
428 				       APDS9960_AICLEAR_REG, 0)) {
429 			ret = -EIO;
430 		}
431 		break;
432 	default:
433 		return -ENOTSUP;
434 	}
435 
436 	return ret;
437 }
438 #endif
439 
apds9960_init(const struct device * dev)440 static int apds9960_init(const struct device *dev)
441 {
442 	const struct apds9960_config *config = dev->config;
443 	struct apds9960_data *data = dev->data;
444 
445 	/* Initialize time 5.7ms */
446 	k_sleep(K_MSEC(6));
447 
448 	if (!device_is_ready(config->i2c.bus)) {
449 		LOG_ERR("Bus device is not ready");
450 		return -EINVAL;
451 	}
452 
453 	(void)memset(data->sample_crgb, 0, sizeof(data->sample_crgb));
454 	data->pdata = 0U;
455 
456 	if (apds9960_sensor_setup(dev) < 0) {
457 		LOG_ERR("Failed to setup device!");
458 		return -EIO;
459 	}
460 
461 	if (apds9960_init_interrupt(dev) < 0) {
462 		LOG_ERR("Failed to initialize interrupt!");
463 		return -EIO;
464 	}
465 
466 	return 0;
467 }
468 
469 static const struct sensor_driver_api apds9960_driver_api = {
470 	.sample_fetch = &apds9960_sample_fetch,
471 	.channel_get = &apds9960_channel_get,
472 #ifdef CONFIG_APDS9960_TRIGGER
473 	.attr_set = apds9960_attr_set,
474 	.trigger_set = apds9960_trigger_set,
475 #endif
476 };
477 
478 static const struct apds9960_config apds9960_config = {
479 	.i2c = I2C_DT_SPEC_INST_GET(0),
480 	.int_gpio = GPIO_DT_SPEC_INST_GET(0, int_gpios),
481 #if CONFIG_APDS9960_PGAIN_8X
482 	.pgain = APDS9960_PGAIN_8X,
483 #elif CONFIG_APDS9960_PGAIN_4X
484 	.pgain = APDS9960_PGAIN_4X,
485 #elif CONFIG_APDS9960_PGAIN_2X
486 	.pgain = APDS9960_PGAIN_2X,
487 #else
488 	.pgain = APDS9960_PGAIN_1X,
489 #endif
490 #if CONFIG_APDS9960_AGAIN_64X
491 	.again = APDS9960_AGAIN_64X,
492 #elif CONFIG_APDS9960_AGAIN_16X
493 	.again = APDS9960_AGAIN_16X,
494 #elif CONFIG_APDS9960_AGAIN_4X
495 	.again = APDS9960_AGAIN_4X,
496 #else
497 	.again = APDS9960_AGAIN_1X,
498 #endif
499 #if CONFIG_APDS9960_PPULSE_LENGTH_32US
500 	.ppcount = APDS9960_PPULSE_LENGTH_32US |
501 		   (CONFIG_APDS9960_PPULSE_COUNT - 1),
502 #elif CONFIG_APDS9960_PPULSE_LENGTH_16US
503 	.ppcount = APDS9960_PPULSE_LENGTH_16US |
504 		   (CONFIG_APDS9960_PPULSE_COUNT - 1),
505 #elif CONFIG_APDS9960_PPULSE_LENGTH_8US
506 	.ppcount = APDS9960_PPULSE_LENGTH_8US |
507 		   (CONFIG_APDS9960_PPULSE_COUNT - 1),
508 #else
509 	.ppcount = APDS9960_PPULSE_LENGTH_4US |
510 		   (CONFIG_APDS9960_PPULSE_COUNT - 1),
511 #endif
512 #if CONFIG_APDS9960_PLED_BOOST_300PCT
513 	.pled_boost = APDS9960_PLED_BOOST_300,
514 #elif CONFIG_APDS9960_PLED_BOOST_200PCT
515 	.pled_boost = APDS9960_PLED_BOOST_200,
516 #elif CONFIG_APDS9960_PLED_BOOST_150PCT
517 	.pled_boost = APDS9960_PLED_BOOST_150,
518 #else
519 	.pled_boost = APDS9960_PLED_BOOST_100,
520 #endif
521 };
522 
523 static struct apds9960_data apds9960_data;
524 
525 PM_DEVICE_DT_INST_DEFINE(0, apds9960_pm_action);
526 
527 SENSOR_DEVICE_DT_INST_DEFINE(0, apds9960_init,
528 	      PM_DEVICE_DT_INST_GET(0), &apds9960_data, &apds9960_config,
529 	      POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &apds9960_driver_api);
530