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