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