1 /*
2  * Copyright (c) 2022 Yonatan Schachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <zephyr/drivers/hwinfo.h>
9 #include <hardware/flash.h>
10 #include <hardware/structs/vreg_and_chip_reset.h>
11 
12 #define FLASH_RUID_DATA_BYTES 8
13 
14 #define HAD_RUN_BIT BIT(VREG_AND_CHIP_RESET_CHIP_RESET_HAD_RUN_LSB)
15 #define HAD_PSM_RESTART_BIT BIT(VREG_AND_CHIP_RESET_CHIP_RESET_HAD_PSM_RESTART_LSB)
16 #define HAD_POR_BIT BIT(VREG_AND_CHIP_RESET_CHIP_RESET_HAD_POR_LSB)
17 
z_impl_hwinfo_get_device_id(uint8_t * buffer,size_t length)18 ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length)
19 {
20 	uint8_t id[FLASH_RUID_DATA_BYTES];
21 	uint32_t key;
22 
23 	/*
24 	 * flash_get_unique_id temporarily disables XIP to query the
25 	 * flash for its ID. If the CPU is interrupted while XIP is
26 	 * disabled, it will halt. Therefore, interrupts must be disabled
27 	 * before fetching the ID.
28 	 */
29 	key = irq_lock();
30 	flash_get_unique_id(id);
31 	irq_unlock(key);
32 
33 	if (length > sizeof(id)) {
34 		length = sizeof(id);
35 	}
36 	memcpy(buffer, id, length);
37 
38 	return length;
39 }
40 
z_impl_hwinfo_get_reset_cause(uint32_t * cause)41 int z_impl_hwinfo_get_reset_cause(uint32_t *cause)
42 {
43 	uint32_t flags = 0;
44 	uint32_t reset_register = vreg_and_chip_reset_hw->chip_reset;
45 
46 	if (reset_register & HAD_POR_BIT) {
47 		flags |= RESET_POR;
48 	}
49 
50 	if (reset_register & HAD_RUN_BIT) {
51 		flags |= RESET_PIN;
52 	}
53 
54 	if (reset_register & HAD_PSM_RESTART_BIT) {
55 		flags |= RESET_DEBUG;
56 	}
57 
58 	*cause = flags;
59 	return 0;
60 }
61 
z_impl_hwinfo_clear_reset_cause(void)62 int z_impl_hwinfo_clear_reset_cause(void)
63 {
64 	/* The reset register can't be modified, nothing to do. */
65 
66 	return -ENOSYS;
67 }
68 
z_impl_hwinfo_get_supported_reset_cause(uint32_t * supported)69 int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported)
70 {
71 	*supported = RESET_PIN | RESET_DEBUG | RESET_POR;
72 
73 	return 0;
74 }
75