1 /*
2  * Copyright (c) 2019 STMicroelectronics
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_INCLUDE_DRIVERS_HSEM_STM32_HSEM_H_
7 #define ZEPHYR_INCLUDE_DRIVERS_HSEM_STM32_HSEM_H_
8 
9 #include <soc.h>
10 #include <stm32_ll_hsem.h>
11 #include <zephyr/kernel.h>
12 
13 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE)
14 /** HW semaphore Complement ID list defined in hw_conf.h from STM32WB
15  * and used also for H7 dualcore targets
16  */
17 /**
18  *  Index of the semaphore used by CPU2 to prevent the CPU1 to either write or
19  *  erase data in flash. The CPU1 shall not either write or erase in flash when
20  *  this semaphore is taken by the CPU2. When the CPU1 needs to either write or
21  *  erase in flash, it shall first get the semaphore and release it just
22  *  after writing a raw (64bits data) or erasing one sector.
23  *  On v1.4.0 and older CPU2 wireless firmware, this semaphore is unused and
24  *  CPU2 is using PES bit. By default, CPU2 is using the PES bit to protect its
25  *  timing. The CPU1 may request the CPU2 to use the semaphore instead of the
26  *  PES bit by sending the system command SHCI_C2_SetFlashActivityControl()
27  */
28 #define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID                    7U
29 
30 /**
31  *  Index of the semaphore used by CPU1 to prevent the CPU2 to either write or
32  *  erase data in flash. In order to protect its timing, the CPU1 may get this
33  *  semaphore to prevent the  CPU2 to either write or erase in flash
34  *  (as this will stall both CPUs)
35  *  The PES bit shall not be used as this may stall the CPU2 in some cases.
36  */
37 #define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID                    6U
38 
39 /**
40  *  Index of the semaphore used to manage the CLK48 clock configuration
41  *  When the USB is required, this semaphore shall be taken before configuring
42  *  the CLK48 for USB and should be released after the application switch OFF
43  *  the clock when the USB is not used anymore. When using the RNG, it is good
44  *  enough to use CFG_HW_RNG_SEMID to control CLK48.
45  *  More details in AN5289
46  */
47 #define CFG_HW_CLK48_CONFIG_SEMID                               5U
48 #define CFG_HW_RCC_CRRCR_CCIPR_SEMID     CFG_HW_CLK48_CONFIG_SEMID
49 
50 /* Index of the semaphore used to manage the entry Stop Mode procedure */
51 #define CFG_HW_ENTRY_STOP_MODE_SEMID                            4U
52 #define CFG_HW_ENTRY_STOP_MODE_MASK_SEMID   (1U << CFG_HW_ENTRY_STOP_MODE_SEMID)
53 
54 /* Index of the semaphore used to access the RCC */
55 #define CFG_HW_RCC_SEMID                                        3U
56 
57 /* Index of the semaphore used to access the FLASH */
58 #define CFG_HW_FLASH_SEMID                                      2U
59 
60 /* Index of the semaphore used to access the PKA */
61 #define CFG_HW_PKA_SEMID                                        1U
62 
63 /* Index of the semaphore used to access the RNG */
64 #define CFG_HW_RNG_SEMID                                        0U
65 
66 /** Index of the semaphore used to access GPIO */
67 #define CFG_HW_GPIO_SEMID                                       8U
68 
69 /** Index of the semaphore used to access the EXTI */
70 #define CFG_HW_EXTI_SEMID                                       9U
71 
72 /** Index of the semaphore for CPU1 mailbox */
73 #define CFG_HW_IPM_CPU1_SEMID                                   10U
74 
75 /** Index of the semaphore for CPU2 mailbox */
76 #define CFG_HW_IPM_CPU2_SEMID                                   11U
77 
78 #elif defined(CONFIG_SOC_SERIES_STM32MP1X)
79 /** HW semaphore from STM32MP1
80  * EXTI and GPIO are inherited from STM32MP1 Linux.
81  * Other SEMID are not used by linux and must not be used here,
82  * but reserved for MPU.
83  */
84 /** Index of the semaphore used to access GPIO */
85 #define CFG_HW_GPIO_SEMID                     0U
86 
87 /** Index of the semaphore used to access the EXTI */
88 #define CFG_HW_EXTI_SEMID                     1U
89 
90 #else
91 /** Fake semaphore ID definition for compilation purpose only */
92 #define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID  0U
93 #define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID  0U
94 #define CFG_HW_CLK48_CONFIG_SEMID             0U
95 #define CFG_HW_RCC_CRRCR_CCIPR_SEMID          0U
96 #define CFG_HW_ENTRY_STOP_MODE_SEMID          0U
97 #define CFG_HW_RCC_SEMID                      0U
98 #define CFG_HW_FLASH_SEMID                    0U
99 #define CFG_HW_PKA_SEMID                      0U
100 #define CFG_HW_RNG_SEMID                      0U
101 #define CFG_HW_GPIO_SEMID                     0U
102 #define CFG_HW_EXTI_SEMID                     0U
103 #define CFG_HW_IPM_CPU1_SEMID                 0U
104 #define CFG_HW_IPM_CPU2_SEMID                 0U
105 
106 #endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */
107 
108 /** Hardware Semaphore wait forever value */
109 #define HSEM_LOCK_WAIT_FOREVER    0xFFFFFFFFU
110 /** Hardware Semaphore default retry value */
111 #define HSEM_LOCK_DEFAULT_RETRY       0x100000U
112 
113 /**
114  * @brief Lock Hardware Semaphore
115  */
z_stm32_hsem_lock(uint32_t hsem,uint32_t retry)116 static inline void z_stm32_hsem_lock(uint32_t  hsem, uint32_t retry)
117 {
118 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) \
119 	|| defined(CONFIG_SOC_SERIES_STM32MP1X)
120 
121 	while (LL_HSEM_1StepLock(HSEM, hsem)) {
122 		if (retry != HSEM_LOCK_WAIT_FOREVER) {
123 			retry--;
124 			if (retry == 0) {
125 				k_panic();
126 			}
127 		}
128 	}
129 #endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE || ... */
130 }
131 
132 /**
133  * @brief Try to lock Hardware Semaphore
134  */
z_stm32_hsem_try_lock(uint32_t hsem)135 static inline int z_stm32_hsem_try_lock(uint32_t hsem)
136 {
137 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) \
138 	|| defined(CONFIG_SOC_SERIES_STM32MP1X)
139 
140 	if (LL_HSEM_1StepLock(HSEM, hsem)) {
141 		return -EAGAIN;
142 	}
143 #endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE || ... */
144 
145 	return 0;
146 }
147 
148 /**
149  * @brief Release Hardware Semaphore
150  */
z_stm32_hsem_unlock(uint32_t hsem)151 static inline void z_stm32_hsem_unlock(uint32_t  hsem)
152 {
153 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) \
154 	|| defined(CONFIG_SOC_SERIES_STM32MP1X)
155 	LL_HSEM_ReleaseLock(HSEM, hsem, 0);
156 #endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE || ... */
157 }
158 
159 /**
160  * @brief Indicates whether Hardware Semaphore is owned by this core
161  */
z_stm32_hsem_is_owned(uint32_t hsem)162 static inline bool z_stm32_hsem_is_owned(uint32_t hsem)
163 {
164 	bool owned = false;
165 
166 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) \
167 	|| defined(CONFIG_SOC_SERIES_STM32MP1X)
168 
169 	owned = LL_HSEM_GetCoreId(HSEM, hsem) == LL_HSEM_COREID;
170 #endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE || ... */
171 
172 	return owned;
173 }
174 
175 #endif /* ZEPHYR_INCLUDE_DRIVERS_HSEM_STM32_HSEM_H_ */
176