1 /*
2 * Copyright 2017-2019, 2022 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_sema4.h"
9
10 /******************************************************************************
11 * Definitions
12 *****************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.sema4"
17 #endif
18
19 /* The first number write to RSTGDP when reset SEMA4 gate. */
20 #define SEMA4_GATE_RESET_PATTERN_1 (0xE2U)
21 /* The second number write to RSTGDP when reset SEMA4 gate. */
22 #define SEMA4_GATE_RESET_PATTERN_2 (0x1DU)
23
24 /* The first number write to RSTGDP when reset SEMA4 gate IRQ notification. */
25 #define SEMA4_GATE_IRQ_RESET_PATTERN_1 (0x47U)
26 /* The second number write to RSTGDP when reset SEMA4 gate IRQ notification. */
27 #define SEMA4_GATE_IRQ_RESET_PATTERN_2 (0xB8U)
28
29 #define SEMA4_RSTGT_RSTNSM_MASK (0x30U)
30
31 #define SEMA4_RSTNTF_RSTNSM_MASK (0x30U)
32
33 /*******************************************************************************
34 * Prototypes
35 ******************************************************************************/
36
37 #if defined(SEMA4_CLOCKS)
38 /*!
39 * @brief Get instance number for SEMA4 module.
40 *
41 * @param base SEMA4 peripheral base address.
42 */
43 uint32_t SEMA4_GetInstance(SEMA4_Type *base);
44 #endif
45
46 /*******************************************************************************
47 * Variables
48 ******************************************************************************/
49
50 #if defined(SEMA4_CLOCKS)
51 /*! @brief Pointers to sema4 bases for each instance. */
52 static SEMA4_Type *const s_sema4Bases[] = SEMA4_BASE_PTRS;
53 #endif
54
55 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
56 #if defined(SEMA4_CLOCKS)
57 /*! @brief Pointers to sema4 clocks for each instance. */
58 static const clock_ip_name_t s_sema4Clocks[] = SEMA4_CLOCKS;
59 #endif
60 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
61
62 /******************************************************************************
63 * CODE
64 *****************************************************************************/
65
66 #if defined(SEMA4_CLOCKS)
SEMA4_GetInstance(SEMA4_Type * base)67 uint32_t SEMA4_GetInstance(SEMA4_Type *base)
68 {
69 uint32_t instance;
70
71 /* Find the instance index from base address mappings. */
72 for (instance = 0; instance < ARRAY_SIZE(s_sema4Bases); instance++)
73 {
74 if (s_sema4Bases[instance] == base)
75 {
76 break;
77 }
78 }
79
80 assert(instance < ARRAY_SIZE(s_sema4Bases));
81
82 return instance;
83 }
84 #endif
85
86 /*!
87 * brief Initializes the SEMA4 module.
88 *
89 * This function initializes the SEMA4 module. It only enables the clock but does
90 * not reset the gates because the module might be used by other processors
91 * at the same time. To reset the gates, call either SEMA4_ResetGate or
92 * SEMA4_ResetAllGates function.
93 *
94 * param base SEMA4 peripheral base address.
95 */
SEMA4_Init(SEMA4_Type * base)96 void SEMA4_Init(SEMA4_Type *base)
97 {
98 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
99 #if defined(SEMA4_CLOCKS)
100 CLOCK_EnableClock(s_sema4Clocks[SEMA4_GetInstance(base)]);
101 #endif
102 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
103 }
104
105 /*!
106 * brief De-initializes the SEMA4 module.
107 *
108 * This function de-initializes the SEMA4 module. It only disables the clock.
109 *
110 * param base SEMA4 peripheral base address.
111 */
SEMA4_Deinit(SEMA4_Type * base)112 void SEMA4_Deinit(SEMA4_Type *base)
113 {
114 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
115 #if defined(SEMA4_CLOCKS)
116 CLOCK_DisableClock(s_sema4Clocks[SEMA4_GetInstance(base)]);
117 #endif
118 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
119 }
120
121 /*!
122 * brief Tries to lock the SEMA4 gate.
123 *
124 * This function tries to lock the specific SEMA4 gate. If the gate has been
125 * locked by another processor, this function returns an error code.
126 *
127 * param base SEMA4 peripheral base address.
128 * param gateNum Gate number to lock.
129 * param procNum Current processor number.
130 *
131 * retval kStatus_Success Lock the sema4 gate successfully.
132 * retval kStatus_Fail Sema4 gate has been locked by another processor.
133 */
SEMA4_TryLock(SEMA4_Type * base,uint8_t gateNum,uint8_t procNum)134 status_t SEMA4_TryLock(SEMA4_Type *base, uint8_t gateNum, uint8_t procNum)
135 {
136 status_t status;
137
138 assert(gateNum < (uint8_t)FSL_FEATURE_SEMA4_GATE_COUNT);
139
140 ++procNum;
141
142 /* Try to lock. */
143 SEMA4_GATEn(base, gateNum) = procNum;
144
145 /* Check locked or not. */
146 if (procNum != SEMA4_GATEn(base, gateNum))
147 {
148 status = kStatus_Fail;
149 }
150 else
151 {
152 status = kStatus_Success;
153 }
154
155 return status;
156 }
157
158 /*!
159 * brief Locks the SEMA4 gate.
160 *
161 * This function locks the specific SEMA4 gate. If the gate has been
162 * locked by other processors, this function waits until it is unlocked and then
163 * lock it.
164 *
165 * param base SEMA4 peripheral base address.
166 * param gateNum Gate number to lock.
167 * param procNum Current processor number.
168 */
SEMA4_Lock(SEMA4_Type * base,uint8_t gateNum,uint8_t procNum)169 void SEMA4_Lock(SEMA4_Type *base, uint8_t gateNum, uint8_t procNum)
170 {
171 while (kStatus_Success != SEMA4_TryLock(base, gateNum, procNum))
172 {
173 }
174 }
175
176 /*!
177 * brief Resets the SEMA4 gate to an unlocked status.
178 *
179 * This function resets a SEMA4 gate to an unlocked status.
180 *
181 * param base SEMA4 peripheral base address.
182 * param gateNum Gate number.
183 *
184 * retval kStatus_Success SEMA4 gate is reset successfully.
185 * retval kStatus_Fail Some other reset process is ongoing.
186 */
SEMA4_ResetGate(SEMA4_Type * base,uint8_t gateNum)187 status_t SEMA4_ResetGate(SEMA4_Type *base, uint8_t gateNum)
188 {
189 status_t status;
190
191 /*
192 * Reset all gates if gateNum >= SEMA4_GATE_NUM_RESET_ALL
193 * Reset specific gate if gateNum < FSL_FEATURE_SEMA4_GATE_COUNT
194 */
195 assert(!((gateNum < SEMA4_GATE_NUM_RESET_ALL) && (gateNum >= (uint8_t)FSL_FEATURE_SEMA4_GATE_COUNT)));
196
197 /* Check whether some reset is ongoing. */
198 if (0U != (base->RSTGT & SEMA4_RSTGT_RSTNSM_MASK))
199 {
200 status = kStatus_Fail;
201 }
202 else
203 {
204 /* First step. */
205 base->RSTGT = SEMA4_RSTGT_RSTGSM_RSTGMS_RSTGDP(SEMA4_GATE_RESET_PATTERN_1);
206 /* Second step. */
207 base->RSTGT = SEMA4_RSTGT_RSTGSM_RSTGMS_RSTGDP(SEMA4_GATE_RESET_PATTERN_2) | SEMA4_RSTGT_RSTGTN(gateNum);
208
209 status = kStatus_Success;
210 }
211
212 return status;
213 }
214
215 /*!
216 * brief Resets the SEMA4 gate IRQ notification.
217 *
218 * This function resets a SEMA4 gate IRQ notification.
219 *
220 * param base SEMA4 peripheral base address.
221 * param gateNum Gate number.
222 *
223 * retval kStatus_Success Reset successfully.
224 * retval kStatus_Fail Some other reset process is ongoing.
225 */
SEMA4_ResetGateNotify(SEMA4_Type * base,uint8_t gateNum)226 status_t SEMA4_ResetGateNotify(SEMA4_Type *base, uint8_t gateNum)
227 {
228 status_t status;
229
230 /*
231 * Reset all gates if gateNum >= SEMA4_GATE_NUM_RESET_ALL
232 * Reset specific gate if gateNum < FSL_FEATURE_SEMA4_GATE_COUNT
233 */
234 assert(!((gateNum < (uint8_t)SEMA4_GATE_NUM_RESET_ALL) && (gateNum >= (uint8_t)FSL_FEATURE_SEMA4_GATE_COUNT)));
235
236 /* Check whether some reset is ongoing. */
237 if (0U != (base->RSTNTF & SEMA4_RSTNTF_RSTNSM_MASK))
238 {
239 status = kStatus_Fail;
240 }
241 else
242 {
243 /* First step. */
244 base->RSTNTF = SEMA4_RSTNTF_RSTNSM_RSTNMS_RSTNDP(SEMA4_GATE_IRQ_RESET_PATTERN_1);
245 /* Second step. */
246 base->RSTNTF = SEMA4_RSTNTF_RSTNSM_RSTNMS_RSTNDP(SEMA4_GATE_IRQ_RESET_PATTERN_2) | SEMA4_RSTNTF_RSTNTN(gateNum);
247
248 status = kStatus_Success;
249 }
250
251 return status;
252 }
253