1 /*
2 * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
3 *
4 * This file is part of VL53L1 Core and is dual licensed,
5 * either 'STMicroelectronics
6 * Proprietary license'
7 * or 'BSD 3-clause "New" or "Revised" License' , at your option.
8 *
9 ********************************************************************************
10 *
11 * 'STMicroelectronics Proprietary license'
12 *
13 ********************************************************************************
14 *
15 * License terms: STMicroelectronics Proprietary in accordance with licensing
16 * terms at www.st.com/sla0081
17 *
18 * STMicroelectronics confidential
19 * Reproduction and Communication of this document is strictly prohibited unless
20 * specifically authorized in writing by STMicroelectronics.
21 *
22 *
23 ********************************************************************************
24 *
25 * Alternatively, VL53L1 Core may be distributed under the terms of
26 * 'BSD 3-clause "New" or "Revised" License', in which case the following
27 * provisions apply instead of the ones mentioned above :
28 *
29 ********************************************************************************
30 *
31 * License terms: BSD 3-clause "New" or "Revised" License.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions are met:
35 *
36 * 1. Redistributions of source code must retain the above copyright notice, this
37 * list of conditions and the following disclaimer.
38 *
39 * 2. Redistributions in binary form must reproduce the above copyright notice,
40 * this list of conditions and the following disclaimer in the documentation
41 * and/or other materials provided with the distribution.
42 *
43 * 3. Neither the name of the copyright holder nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
55 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 *
58 *
59 ********************************************************************************
60 *
61 */
62 
63 /**
64  * @file  vl53l1_wait.c
65  *
66  * @brief EwokPlus25 low level Driver wait function definition
67  */
68 
69 
70 #include "vl53l1_ll_def.h"
71 #include "vl53l1_ll_device.h"
72 #include "vl53l1_platform.h"
73 #include "vl53l1_core.h"
74 #include "vl53l1_silicon_core.h"
75 #include "vl53l1_wait.h"
76 #include "vl53l1_register_settings.h"
77 
78 
79 #define LOG_FUNCTION_START(fmt, ...) \
80 	_LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__)
81 #define LOG_FUNCTION_END(status, ...) \
82 	_LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__)
83 #define LOG_FUNCTION_END_FMT(status, fmt, ...) \
84 	_LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, status, \
85 		fmt, ##__VA_ARGS__)
86 
87 
VL53L1_wait_for_boot_completion(VL53L1_DEV Dev)88 VL53L1_Error VL53L1_wait_for_boot_completion(
89 	VL53L1_DEV     Dev)
90 {
91 
92 	/* Waits for firmware boot to finish
93 	 */
94 
95 	VL53L1_Error status = VL53L1_ERROR_NONE;
96 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
97 
98 	uint8_t      fw_ready  = 0;
99 
100 	LOG_FUNCTION_START("");
101 
102 	if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
103 
104 		/* blocking version */
105 
106 		status =
107 			VL53L1_poll_for_boot_completion(
108 				Dev,
109 				VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS);
110 
111 	} else {
112 
113 		/* implement non blocking version below */
114 
115 		fw_ready = 0;
116 		while (fw_ready == 0x00 && status == VL53L1_ERROR_NONE) {
117 			status = VL53L1_is_boot_complete(
118 				Dev,
119 				&fw_ready);
120 
121 			if (status == VL53L1_ERROR_NONE) {
122 				status = VL53L1_WaitMs(
123 					Dev,
124 					VL53L1_POLLING_DELAY_MS);
125 			}
126 		}
127 	}
128 
129 	LOG_FUNCTION_END(status);
130 
131 	return status;
132 
133 }
134 
135 
VL53L1_wait_for_firmware_ready(VL53L1_DEV Dev)136 VL53L1_Error VL53L1_wait_for_firmware_ready(
137 	VL53L1_DEV     Dev)
138 {
139 
140 	/* If in timed mode or single shot then check firmware is ready
141 	 * before sending handshake
142 	 */
143 
144 	VL53L1_Error status = VL53L1_ERROR_NONE;
145 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
146 
147 	uint8_t      fw_ready  = 0;
148 	uint8_t      mode_start  = 0;
149 
150 	LOG_FUNCTION_START("");
151 
152 	/* Filter out tje measure mode part of the mode
153 	 * start register
154 	 */
155 	mode_start =
156 		pdev->sys_ctrl.system__mode_start &
157 		VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK;
158 
159 	/*
160 	 * conditional wait for firmware ready
161 	 * only waits for timed and single shot modes
162 	 */
163 
164 	if ((mode_start == VL53L1_DEVICEMEASUREMENTMODE_TIMED) ||
165 		(mode_start == VL53L1_DEVICEMEASUREMENTMODE_SINGLESHOT)) {
166 
167 		if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
168 
169 			/* blocking version */
170 
171 			status =
172 				VL53L1_poll_for_firmware_ready(
173 					Dev,
174 					VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
175 
176 		} else {
177 
178 			/* implement non blocking version below */
179 
180 			fw_ready = 0;
181 			while (fw_ready == 0x00 && status == VL53L1_ERROR_NONE) {
182 				status = VL53L1_is_firmware_ready(
183 					Dev,
184 					&fw_ready);
185 
186 				if (status == VL53L1_ERROR_NONE) {
187 					status = VL53L1_WaitMs(
188 						Dev,
189 						VL53L1_POLLING_DELAY_MS);
190 				}
191 			}
192 		}
193 	}
194 
195 	LOG_FUNCTION_END(status);
196 
197 	return status;
198 }
199 
200 
VL53L1_wait_for_range_completion(VL53L1_DEV Dev)201 VL53L1_Error VL53L1_wait_for_range_completion(
202 	VL53L1_DEV     Dev)
203 {
204 
205 	/* Wrapper function for waiting for range completion
206 	 */
207 
208 	VL53L1_Error status = VL53L1_ERROR_NONE;
209 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
210 
211 	uint8_t      data_ready  = 0;
212 
213 	LOG_FUNCTION_START("");
214 
215 	if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
216 
217 		/* blocking version */
218 
219 		status =
220 			VL53L1_poll_for_range_completion(
221 				Dev,
222 				VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
223 
224 	} else {
225 
226 		/* implement non blocking version below */
227 
228 		data_ready = 0;
229 		while (data_ready == 0x00 && status == VL53L1_ERROR_NONE) {
230 			status = VL53L1_is_new_data_ready(
231 				Dev,
232 				&data_ready);
233 
234 			if (status == VL53L1_ERROR_NONE) {
235 				status = VL53L1_WaitMs(
236 					Dev,
237 					VL53L1_POLLING_DELAY_MS);
238 			}
239 		}
240 	}
241 
242 	LOG_FUNCTION_END(status);
243 
244 	return status;
245 }
246 
247 
VL53L1_wait_for_test_completion(VL53L1_DEV Dev)248 VL53L1_Error VL53L1_wait_for_test_completion(
249 	VL53L1_DEV     Dev)
250 {
251 
252 	/* Wrapper function for waiting for test mode completion
253 	 */
254 
255 	VL53L1_Error status = VL53L1_ERROR_NONE;
256 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
257 
258 	uint8_t      data_ready  = 0;
259 
260 	LOG_FUNCTION_START("");
261 
262 	if (pdev->wait_method == VL53L1_WAIT_METHOD_BLOCKING) {
263 
264 		/* blocking version */
265 
266 		status =
267 			VL53L1_poll_for_range_completion(
268 				Dev,
269 				VL53L1_TEST_COMPLETION_POLLING_TIMEOUT_MS);
270 
271 	} else {
272 
273 		/* implement non blocking version below */
274 
275 		data_ready = 0;
276 		while (data_ready == 0x00 && status == VL53L1_ERROR_NONE) {
277 			status = VL53L1_is_new_data_ready(
278 				Dev,
279 				&data_ready);
280 
281 			if (status == VL53L1_ERROR_NONE) {
282 				status = VL53L1_WaitMs(
283 					Dev,
284 					VL53L1_POLLING_DELAY_MS);
285 			}
286 		}
287 	}
288 
289 	LOG_FUNCTION_END(status);
290 
291 	return status;
292 }
293 
294 
295 
296 
VL53L1_is_boot_complete(VL53L1_DEV Dev,uint8_t * pready)297 VL53L1_Error VL53L1_is_boot_complete(
298 	VL53L1_DEV     Dev,
299 	uint8_t       *pready)
300 {
301 	/**
302 	 * Determines if the firmware finished booting by reading
303 	 * bit 0 of firmware__system_status register
304 	 */
305 
306 	VL53L1_Error status = VL53L1_ERROR_NONE;
307 	uint8_t  firmware__system_status = 0;
308 
309 	LOG_FUNCTION_START("");
310 
311 	/* read current range interrupt state */
312 
313 	status =
314 		VL53L1_RdByte(
315 			Dev,
316 			VL53L1_FIRMWARE__SYSTEM_STATUS,
317 			&firmware__system_status);
318 
319 	/* set *pready = 1 if new range data ready complete
320 	 * zero otherwise
321 	 */
322 
323 	if ((firmware__system_status & 0x01) == 0x01) {
324 		*pready = 0x01;
325 		VL53L1_init_ll_driver_state(
326 			Dev,
327 			VL53L1_DEVICESTATE_SW_STANDBY);
328 	} else {
329 		*pready = 0x00;
330 		VL53L1_init_ll_driver_state(
331 			Dev,
332 			VL53L1_DEVICESTATE_FW_COLDBOOT);
333 	}
334 
335 	LOG_FUNCTION_END(status);
336 
337 	return status;
338 }
339 
340 
VL53L1_is_firmware_ready(VL53L1_DEV Dev,uint8_t * pready)341 VL53L1_Error VL53L1_is_firmware_ready(
342 	VL53L1_DEV     Dev,
343 	uint8_t       *pready)
344 {
345 	/**
346 	 * Determines if the firmware is ready to range
347 	 */
348 
349 	VL53L1_Error status = VL53L1_ERROR_NONE;
350 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
351 
352 	LOG_FUNCTION_START("");
353 
354 	status = VL53L1_is_firmware_ready_silicon(
355 					Dev,
356 					pready);
357 
358 	pdev->fw_ready = *pready;
359 
360 	LOG_FUNCTION_END(status);
361 
362 	return status;
363 }
364 
365 
VL53L1_is_new_data_ready(VL53L1_DEV Dev,uint8_t * pready)366 VL53L1_Error VL53L1_is_new_data_ready(
367 	VL53L1_DEV     Dev,
368 	uint8_t       *pready)
369 {
370 	/**
371 	 * Determines if new range data is ready by reading bit 0 of
372 	 * VL53L1_GPIO__TIO_HV_STATUS to determine the current state
373 	 * of output interrupt pin
374 	 */
375 
376 	VL53L1_Error status = VL53L1_ERROR_NONE;
377 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
378 
379 	uint8_t  gpio__mux_active_high_hv = 0;
380 	uint8_t  gpio__tio_hv_status      = 0;
381 	uint8_t  interrupt_ready          = 0;
382 
383 	LOG_FUNCTION_START("");
384 
385 	gpio__mux_active_high_hv =
386 			pdev->stat_cfg.gpio_hv_mux__ctrl &
387 			VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_MASK;
388 
389 	if (gpio__mux_active_high_hv == VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH)
390 		interrupt_ready = 0x01;
391 	else
392 		interrupt_ready = 0x00;
393 
394 	/* read current range interrupt state */
395 
396 	status = VL53L1_RdByte(
397 					Dev,
398 					VL53L1_GPIO__TIO_HV_STATUS,
399 					&gpio__tio_hv_status);
400 
401 	/* set *pready = 1 if new range data ready complete zero otherwise */
402 
403 	if ((gpio__tio_hv_status & 0x01) == interrupt_ready)
404 		*pready = 0x01;
405 	else
406 		*pready = 0x00;
407 
408 	LOG_FUNCTION_END(status);
409 
410 	return status;
411 }
412 
413 
414 
415 
VL53L1_poll_for_boot_completion(VL53L1_DEV Dev,uint32_t timeout_ms)416 VL53L1_Error VL53L1_poll_for_boot_completion(
417 	VL53L1_DEV    Dev,
418 	uint32_t      timeout_ms)
419 {
420 	/**
421 	 * Polls the bit 0 of the FIRMWARE__SYSTEM_STATUS register to see if
422 	 * the firmware is ready.
423 	 */
424 
425 	VL53L1_Error status       = VL53L1_ERROR_NONE;
426 
427 	LOG_FUNCTION_START("");
428 
429 	/* after reset for the firmware blocks I2C access while
430 	 * it copies the NVM data into the G02 host register banks
431 	 * The host must wait the required time to allow the copy
432 	 * to complete before attempting to read the firmware status
433 	 */
434 
435 	status = VL53L1_WaitUs(
436 			Dev,
437 			VL53L1_FIRMWARE_BOOT_TIME_US);
438 
439 	if (status == VL53L1_ERROR_NONE)
440 		status =
441 			VL53L1_WaitValueMaskEx(
442 				Dev,
443 				timeout_ms,
444 				VL53L1_FIRMWARE__SYSTEM_STATUS,
445 				0x01,
446 				0x01,
447 				VL53L1_POLLING_DELAY_MS);
448 
449 	if (status == VL53L1_ERROR_NONE)
450 		VL53L1_init_ll_driver_state(Dev, VL53L1_DEVICESTATE_SW_STANDBY);
451 
452 	LOG_FUNCTION_END(status);
453 
454 	return status;
455 }
456 
457 
VL53L1_poll_for_firmware_ready(VL53L1_DEV Dev,uint32_t timeout_ms)458 VL53L1_Error VL53L1_poll_for_firmware_ready(
459 	VL53L1_DEV    Dev,
460 	uint32_t      timeout_ms)
461 {
462 	/**
463 	 * Polls the bit 0 of the FIRMWARE__SYSTEM_STATUS register to see if
464 	 * the firmware is ready.
465 	 */
466 
467 	VL53L1_Error status          = VL53L1_ERROR_NONE;
468 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
469 
470 	uint32_t     start_time_ms   = 0;
471 	uint32_t     current_time_ms = 0;
472 	int32_t      poll_delay_ms   = VL53L1_POLLING_DELAY_MS;
473 	uint8_t      fw_ready        = 0;
474 
475 	/* calculate time limit in absolute time */
476 
477 	VL53L1_GetTickCount(&start_time_ms); /*lint !e534 ignoring return*/
478 	pdev->fw_ready_poll_duration_ms = 0;
479 
480 	/* wait until firmware is ready, timeout reached on error occurred */
481 
482 	while ((status == VL53L1_ERROR_NONE) &&
483 		   (pdev->fw_ready_poll_duration_ms < timeout_ms) &&
484 		   (fw_ready == 0)) {
485 
486 		status = VL53L1_is_firmware_ready(
487 			Dev,
488 			&fw_ready);
489 
490 		if (status == VL53L1_ERROR_NONE &&
491 			fw_ready == 0 &&
492 			poll_delay_ms > 0) {
493 			status = VL53L1_WaitMs(
494 				Dev,
495 				poll_delay_ms);
496 		}
497 
498 		/*
499 		 * Update polling time (Compare difference rather than
500 		 * absolute to negate 32bit wrap around issue)
501 		 */
502 		VL53L1_GetTickCount(&current_time_ms);  /*lint !e534 ignoring return*/
503 		pdev->fw_ready_poll_duration_ms =
504 				current_time_ms - start_time_ms;
505 	}
506 
507 	if (fw_ready == 0 && status == VL53L1_ERROR_NONE)
508 		status = VL53L1_ERROR_TIME_OUT;
509 
510 	LOG_FUNCTION_END(status);
511 
512 	return status;
513 }
514 
515 
VL53L1_poll_for_range_completion(VL53L1_DEV Dev,uint32_t timeout_ms)516 VL53L1_Error VL53L1_poll_for_range_completion(
517 	VL53L1_DEV     Dev,
518 	uint32_t       timeout_ms)
519 {
520 	/**
521 	 * Polls bit 0 of VL53L1_GPIO__TIO_HV_STATUS to determine
522 	 * the state of output interrupt pin
523 	 *
524 	 * Interrupt may be either active high or active low. Use active_high to
525 	 * select the required level check
526 	 */
527 
528 	VL53L1_Error status = VL53L1_ERROR_NONE;
529 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
530 
531 	uint8_t  gpio__mux_active_high_hv = 0;
532 	uint8_t  interrupt_ready          = 0;
533 
534 	LOG_FUNCTION_START("");
535 
536 	gpio__mux_active_high_hv =
537 			pdev->stat_cfg.gpio_hv_mux__ctrl &
538 			VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_MASK;
539 
540 	if (gpio__mux_active_high_hv == VL53L1_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH)
541 		interrupt_ready = 0x01;
542 	else
543 		interrupt_ready = 0x00;
544 
545 	status =
546 		VL53L1_WaitValueMaskEx(
547 			Dev,
548 			timeout_ms,
549 			VL53L1_GPIO__TIO_HV_STATUS,
550 			interrupt_ready,
551 			0x01,
552 			VL53L1_POLLING_DELAY_MS);
553 
554 	LOG_FUNCTION_END(status);
555 
556 	return status;
557 }
558 
559