1 /*
2  * Copyright (c) 2018 Alexander Wachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <soc.h>
8 #include <stm32_ll_utils.h>
9 #include <stm32_ll_rcc.h>
10 #if defined(CONFIG_SOC_SERIES_STM32H5X)
11 #include <stm32_ll_icache.h>
12 #endif /* CONFIG_SOC_SERIES_STM32H5X */
13 #include <stm32_ll_pwr.h>
14 #include <zephyr/drivers/hwinfo.h>
15 #include <string.h>
16 #include <zephyr/sys/byteorder.h>
17 
18 struct stm32_uid {
19 	uint32_t id[3];
20 };
21 
z_impl_hwinfo_get_device_id(uint8_t * buffer,size_t length)22 ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length)
23 {
24 	struct stm32_uid dev_id;
25 
26 #if defined(CONFIG_SOC_SERIES_STM32H5X)
27 	LL_ICACHE_Disable();
28 #endif /* CONFIG_SOC_SERIES_STM32H5X */
29 
30 	dev_id.id[0] = sys_cpu_to_be32(LL_GetUID_Word2());
31 	dev_id.id[1] = sys_cpu_to_be32(LL_GetUID_Word1());
32 	dev_id.id[2] = sys_cpu_to_be32(LL_GetUID_Word0());
33 
34 #if defined(CONFIG_SOC_SERIES_STM32H5X)
35 	LL_ICACHE_Enable();
36 #endif /* CONFIG_SOC_SERIES_STM32H5X */
37 
38 	if (length > sizeof(dev_id.id)) {
39 		length = sizeof(dev_id.id);
40 	}
41 
42 	memcpy(buffer, dev_id.id, length);
43 
44 	return length;
45 }
46 
47 #if defined(CONFIG_SOC_SERIES_STM32WBAX) || \
48 	defined(CONFIG_SOC_SERIES_STM32WBX) || \
49 	defined(CONFIG_SOC_SERIES_STM32WLX)
50 struct stm32_eui64 {
51 	uint32_t id[2];
52 };
53 
z_impl_hwinfo_get_device_eui64(uint8_t * buffer)54 int z_impl_hwinfo_get_device_eui64(uint8_t *buffer)
55 {
56 	struct stm32_eui64 dev_eui64;
57 
58 	dev_eui64.id[0] = sys_cpu_to_be32(READ_REG(*((uint32_t *)UID64_BASE + 1U)));
59 	dev_eui64.id[1] = sys_cpu_to_be32(READ_REG(*((uint32_t *)UID64_BASE)));
60 
61 	memcpy(buffer, dev_eui64.id, sizeof(dev_eui64));
62 
63 	return 0;
64 }
65 #endif
66 
z_impl_hwinfo_get_reset_cause(uint32_t * cause)67 int z_impl_hwinfo_get_reset_cause(uint32_t *cause)
68 {
69 	uint32_t flags = 0;
70 
71 #if defined(RCC_FLAG_SFTRST)
72 	if (LL_RCC_IsActiveFlag_SFTRST()) {
73 		flags |= RESET_SOFTWARE;
74 	}
75 #endif
76 #if defined(RCC_FLAG_PINRST)
77 	if (LL_RCC_IsActiveFlag_PINRST()) {
78 		flags |= RESET_PIN;
79 	}
80 #endif
81 #if defined(RCC_FLAG_IWDGRST)
82 	if (LL_RCC_IsActiveFlag_IWDGRST()) {
83 		flags |= RESET_WATCHDOG;
84 	}
85 #endif
86 #if defined(RCC_RSR_IWDG1RSTF)
87 	if (LL_RCC_IsActiveFlag_IWDG1RST()) {
88 		flags |= RESET_WATCHDOG;
89 	}
90 #endif
91 #if defined(RCC_RSR_IWDG2RSTF)
92 	if (LL_RCC_IsActiveFlag_IWDG2RST()) {
93 		flags |= RESET_WATCHDOG;
94 	}
95 #endif
96 #if defined(RCC_FLAG_WWDGRST)
97 	if (LL_RCC_IsActiveFlag_WWDGRST()) {
98 		flags |= RESET_WATCHDOG;
99 	}
100 #endif
101 #if defined(RCC_RSR_WWDG1RSTF)
102 	if (LL_RCC_IsActiveFlag_WWDG1RST()) {
103 		flags |= RESET_WATCHDOG;
104 	}
105 #endif
106 #if defined(RCC_RSR_WWDG2RSTF)
107 	if (LL_RCC_IsActiveFlag_WWDG2RST()) {
108 		flags |= RESET_WATCHDOG;
109 	}
110 #endif
111 #if defined(RCC_FLAG_FWRST)
112 	if (LL_RCC_IsActiveFlag_FWRST()) {
113 		flags |= RESET_SECURITY;
114 	}
115 #endif
116 #if defined(RCC_FLAG_BORRST)
117 	if (LL_RCC_IsActiveFlag_BORRST()) {
118 		flags |= RESET_BROWNOUT;
119 	}
120 #endif
121 #if defined(RCC_FLAG_PWRRST)
122 	if (LL_RCC_IsActiveFlag_PWRRST()) {
123 		flags |= RESET_POR;
124 	}
125 #endif
126 #if defined(RCC_FLAG_PORRST)
127 	if (LL_RCC_IsActiveFlag_PORRST()) {
128 		flags |= RESET_POR;
129 	}
130 #endif
131 #if defined(RCC_FLAG_LPWRRST)
132 	if (LL_RCC_IsActiveFlag_LPWRRST()) {
133 		flags |= RESET_LOW_POWER_WAKE;
134 	}
135 #endif
136 
137 #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CORE_CM4)
138 	if (LL_PWR_CPU2_IsActiveFlag_SB()) {
139 		flags |= RESET_LOW_POWER_WAKE;
140 	}
141 #elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CORE_CM7)
142 	if (LL_PWR_CPU_IsActiveFlag_SB()) {
143 		flags |= RESET_LOW_POWER_WAKE;
144 	}
145 #elif defined(CONFIG_SOC_SERIES_STM32MP1X)
146 	if (LL_PWR_MCU_IsActiveFlag_SB()) {
147 		flags |= RESET_LOW_POWER_WAKE;
148 	}
149 #elif defined(CONFIG_SOC_SERIES_STM32WLX) || defined(CONFIG_SOC_SERIES_STM32WBX)
150 	if (LL_PWR_IsActiveFlag_C1SB()) {
151 		flags |= RESET_LOW_POWER_WAKE;
152 	}
153 #elif defined(PWR_FLAG_SB) || defined(PWR_FLAG_SBF)
154 	if (LL_PWR_IsActiveFlag_SB()) {
155 		flags |= RESET_LOW_POWER_WAKE;
156 	}
157 #endif /* PWR_FLAG_SB */
158 
159 	*cause = flags;
160 
161 	return 0;
162 }
163 
z_impl_hwinfo_clear_reset_cause(void)164 int z_impl_hwinfo_clear_reset_cause(void)
165 {
166 	LL_RCC_ClearResetFlags();
167 
168 #if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CORE_CM4)
169 	LL_PWR_ClearFlag_CPU2();
170 #elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CORE_CM7)
171 	LL_PWR_ClearFlag_CPU();
172 #elif defined(CONFIG_SOC_SERIES_STM32H7RSX)
173 	LL_PWR_ClearFlag_STOP_SB();
174 #elif defined(CONFIG_SOC_SERIES_STM32MP1X)
175 	LL_PWR_ClearFlag_MCU();
176 #elif defined(CONFIG_SOC_SERIES_STM32WLX) || defined(CONFIG_SOC_SERIES_STM32WBX)
177 	LL_PWR_ClearFlag_C1STOP_C1STB();
178 #elif defined(CONFIG_SOC_SERIES_STM32U0X) && defined(PWR_FLAG_SB)
179 	LL_PWR_ClearFlag_CSB();
180 #elif defined(PWR_FLAG_SB)
181 	LL_PWR_ClearFlag_SB();
182 #endif /* PWR_FLAG_SB */
183 
184 	return 0;
185 }
186 
z_impl_hwinfo_get_supported_reset_cause(uint32_t * supported)187 int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported)
188 {
189 	*supported = (RESET_PIN
190 		      | RESET_WATCHDOG
191 		      | RESET_SOFTWARE
192 		      | RESET_SECURITY
193 		      | RESET_LOW_POWER_WAKE
194 		      | RESET_POR
195 		      | RESET_BROWNOUT);
196 
197 	return 0;
198 }
199