1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020, 2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_sema42.h"
10 
11 /******************************************************************************
12  * Definitions
13  *****************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.sema42"
18 #endif
19 
20 /* The first number write to RSTGDP when reset SEMA42 gate. */
21 #define SEMA42_GATE_RESET_PATTERN_1 (0xE2U)
22 /* The second number write to RSTGDP when reset SEMA42 gate. */
23 #define SEMA42_GATE_RESET_PATTERN_2 (0x1DU)
24 
25 #if defined(SEMA42_RSTS)
26 #define SEMA42_RESETS_ARRAY SEMA42_RSTS
27 #endif
28 
29 /*******************************************************************************
30  * Prototypes
31  ******************************************************************************/
32 
33 /*!
34  * @brief Get instance number for SEMA42 module.
35  *
36  * @param base SEMA42 peripheral base address.
37  */
38 uint32_t SEMA42_GetInstance(SEMA42_Type *base);
39 
40 /*******************************************************************************
41  * Variables
42  ******************************************************************************/
43 
44 /*! @brief Pointers to sema42 bases for each instance. */
45 static SEMA42_Type *const s_sema42Bases[] = SEMA42_BASE_PTRS;
46 
47 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
48 /*! @brief Pointers to sema42 clocks for each instance. */
49 static const clock_ip_name_t s_sema42Clocks[] = SEMA42_CLOCKS;
50 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
51 
52 #if defined(SEMA42_RESETS_ARRAY)
53 /* Reset array */
54 static const reset_ip_name_t s_sema42Resets[] = SEMA42_RESETS_ARRAY;
55 #endif
56 
57 /******************************************************************************
58  * CODE
59  *****************************************************************************/
60 
SEMA42_GetInstance(SEMA42_Type * base)61 uint32_t SEMA42_GetInstance(SEMA42_Type *base)
62 {
63     uint32_t instance;
64 
65     /* Find the instance index from base address mappings. */
66     /*
67      * $Branch Coverage Justification$
68      * (instance >= ARRAY_SIZE(s_sema42Bases)) not covered. The peripheral base
69      * address is always valid and checked by assert.
70      */
71     for (instance = 0; instance < ARRAY_SIZE(s_sema42Bases); instance++)
72     {
73         /*
74          * $Branch Coverage Justification$
75          * (s_sema42Bases[instance] != base) not covered. The peripheral base
76          * address is always valid and checked by assert.
77          */
78         if (s_sema42Bases[instance] == base)
79         {
80             break;
81         }
82     }
83 
84     assert(instance < ARRAY_SIZE(s_sema42Bases));
85 
86     return instance;
87 }
88 
89 /*!
90  * brief Initializes the SEMA42 module.
91  *
92  * This function initializes the SEMA42 module. It only enables the clock but does
93  * not reset the gates because the module might be used by other processors
94  * at the same time. To reset the gates, call either SEMA42_ResetGate or
95  * SEMA42_ResetAllGates function.
96  *
97  * param base SEMA42 peripheral base address.
98  */
SEMA42_Init(SEMA42_Type * base)99 void SEMA42_Init(SEMA42_Type *base)
100 {
101 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
102     (void)CLOCK_EnableClock(s_sema42Clocks[SEMA42_GetInstance(base)]);
103 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
104 
105 #if defined(SEMA42_RESETS_ARRAY)
106     RESET_ReleasePeripheralReset(s_sema42Resets[SEMA42_GetInstance(base)]);
107 #endif
108 }
109 
110 /*!
111  * brief De-initializes the SEMA42 module.
112  *
113  * This function de-initializes the SEMA42 module. It only disables the clock.
114  *
115  * param base SEMA42 peripheral base address.
116  */
SEMA42_Deinit(SEMA42_Type * base)117 void SEMA42_Deinit(SEMA42_Type *base)
118 {
119 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
120     (void)CLOCK_DisableClock(s_sema42Clocks[SEMA42_GetInstance(base)]);
121 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
122 }
123 
124 /*!
125  * brief Tries to lock the SEMA42 gate.
126  *
127  * This function tries to lock the specific SEMA42 gate. If the gate has been
128  * locked by another processor, this function returns an error code.
129  *
130  * param base SEMA42 peripheral base address.
131  * param gateNum  Gate number to lock.
132  * param procNum  Current processor number.
133  *
134  * retval kStatus_Success     Lock the sema42 gate successfully.
135  * retval kStatus_SEMA42_Busy Sema42 gate has been locked by another processor.
136  */
SEMA42_TryLock(SEMA42_Type * base,uint8_t gateNum,uint8_t procNum)137 status_t SEMA42_TryLock(SEMA42_Type *base, uint8_t gateNum, uint8_t procNum)
138 {
139     status_t status;
140 
141     assert(gateNum < (uint8_t)FSL_FEATURE_SEMA42_GATE_COUNT);
142 
143     ++procNum;
144 
145     /* Try to lock. */
146     SEMA42_GATEn(base, gateNum) = procNum;
147 
148     /* Check locked or not. */
149     if (procNum != SEMA42_GATEn(base, gateNum))
150     {
151         status = kStatus_SEMA42_Busy;
152     }
153     else
154     {
155         status = kStatus_Success;
156     }
157 
158     return status;
159 }
160 
161 /*!
162  * brief Locks the SEMA42 gate.
163  *
164  * This function locks the specific SEMA42 gate. If the gate has been
165  * locked by other processors, this function waits until it is unlocked and then
166  * lock it.
167  *
168  * param base SEMA42 peripheral base address.
169  * param gateNum  Gate number to lock.
170  * param procNum  Current processor number.
171  */
SEMA42_Lock(SEMA42_Type * base,uint8_t gateNum,uint8_t procNum)172 void SEMA42_Lock(SEMA42_Type *base, uint8_t gateNum, uint8_t procNum)
173 {
174     while (kStatus_Success != SEMA42_TryLock(base, gateNum, procNum))
175     {
176     }
177 }
178 
179 /*!
180  * brief Resets the SEMA42 gate to an unlocked status.
181  *
182  * This function resets a SEMA42 gate to an unlocked status.
183  *
184  * param base SEMA42 peripheral base address.
185  * param gateNum  Gate number.
186  *
187  * retval kStatus_Success         SEMA42 gate is reset successfully.
188  * retval kStatus_SEMA42_Reseting Some other reset process is ongoing.
189  */
SEMA42_ResetGate(SEMA42_Type * base,uint8_t gateNum)190 status_t SEMA42_ResetGate(SEMA42_Type *base, uint8_t gateNum)
191 {
192     status_t status;
193 
194     /*
195      * Reset all gates if gateNum >= SEMA42_GATE_NUM_RESET_ALL
196      * Reset specific gate if gateNum < FSL_FEATURE_SEMA42_GATE_COUNT
197      */
198     assert(!((gateNum < SEMA42_GATE_NUM_RESET_ALL) && (gateNum >= (uint8_t)FSL_FEATURE_SEMA42_GATE_COUNT)));
199 
200     /* Check whether some reset is ongoing. */
201     /*
202      * $Branch Coverage Justification$
203      * (0U == (base->RSTGT_R & SEMA42_RSTGT_R_RSTGSM_MASK))) not covered. Test unfeasible,
204      * the reset state is too short to catch.
205      */
206     if (0U != (base->RSTGT_R & SEMA42_RSTGT_R_RSTGSM_MASK))
207     {
208         /*
209          * $Line Coverage Justification$
210          * Block not covered. Test unfeasible, the reset state is too short to catch.
211          */
212         status = kStatus_SEMA42_Reseting;
213     }
214     else
215     {
216         /* First step. */
217         base->RSTGT_W = SEMA42_RSTGT_W_RSTGDP(SEMA42_GATE_RESET_PATTERN_1);
218         /* Second step. */
219         base->RSTGT_W = SEMA42_RSTGT_W_RSTGDP(SEMA42_GATE_RESET_PATTERN_2) | SEMA42_RSTGT_W_RSTGTN(gateNum);
220 
221         status = kStatus_Success;
222     }
223 
224     return status;
225 }
226